예제 #1
0
/*
 * Set the text matrix for writing text.  The translation component of the
 * matrix is the text origin.  If the non-translation components of the
 * matrix differ from the current ones, write a Tm command; if there is only
 * a Y translation, set use_leading so the next text string will be written
 * with ' rather than Tj; otherwise, write a Td command.
 */
static int
pdf_set_text_matrix(gx_device_pdf * pdev)
{
    pdf_text_state_t *pts = pdev->text->text_state;
    stream *s = pdev->strm;

    pts->use_leading = false;
    if (matrix_is_compatible(&pts->out.matrix, &pts->in.matrix)) {
        gs_point dist;
        int code;

        code = set_text_distance(&dist, pts->start.x - pts->line_start.x,
                          pts->start.y - pts->line_start.y, &pts->in.matrix);
        if (code < 0)
            return code;
        if (dist.x == 0 && dist.y < 0) {
            /* Use TL, if needed, and T* or '. */
            float dist_y = (float)-dist.y;

            if (fabs(pts->leading - dist_y) > 0.0005) {
                pprintg1(s, "%g TL\n", dist_y);
                pts->leading = dist_y;
            }
            pts->use_leading = true;
        } else {
            /* Use Td. */
            pprintg2(s, "%g %g Td\n", dist.x, dist.y);
        }
    } else {			/* Use Tm. */
        /*
         * See stream_to_text in gdevpdfu.c for why we need the following
         * matrix adjustments.
         */
        double sx = 72.0 / pdev->HWResolution[0],
            sy = 72.0 / pdev->HWResolution[1];

        pprintg6(s, "%g %g %g %g %g %g Tm\n",
                 pts->in.matrix.xx * sx, pts->in.matrix.xy * sy,
                 pts->in.matrix.yx * sx, pts->in.matrix.yy * sy,
                 pts->start.x * sx, pts->start.y * sy);
    }
    pts->line_start.x = pts->start.x;
    pts->line_start.y = pts->start.y;
    pts->out.matrix = pts->in.matrix;
    return 0;
}
예제 #2
0
/*
 *  Flush text from buffer.
 */
static int
flush_text_buffer(gx_device_pdf *pdev)
{
    pdf_text_state_t *pts = pdev->text->text_state;
    stream *s = pdev->strm;

    if (pts->buffer.count_chars != 0) {
        pdf_font_resource_t *pdfont = pts->in.pdfont;
        int code = pdf_assign_font_object_id(pdev, pdfont);

        if (code < 0)
            return code;
        code = pdf_add_resource(pdev, pdev->substream_Resources, "/Font", (pdf_resource_t *)pdfont);
        if (code < 0)
            return code;
    }
    if (pts->buffer.count_moves > 0) {
        int i, cur = 0;

        if (pts->use_leading)
            stream_puts(s, "T*");
        stream_puts(s, "[");
        for (i = 0; i < pts->buffer.count_moves; ++i) {
            int next = pts->buffer.moves[i].index;

            pdf_put_string(pdev, pts->buffer.chars + cur, next - cur);
            pprintg1(s, "%g", pts->buffer.moves[i].amount);
            cur = next;
        }
        if (pts->buffer.count_chars > cur)
            pdf_put_string(pdev, pts->buffer.chars + cur,
                           pts->buffer.count_chars - cur);
        stream_puts(s, "]TJ\n");
    } else {
        pdf_put_string(pdev, pts->buffer.chars, pts->buffer.count_chars);
        stream_puts(s, (pts->use_leading ? "'\n" : "Tj\n"));
    }
    pts->buffer.count_chars = 0;
    pts->buffer.count_moves = 0;
    pts->use_leading = false;
    return 0;
}
예제 #3
0
/* Write a CMap in its standard (source) format. */
int
psf_write_cmap(const gs_memory_t *mem, 
	       stream *s, const gs_cmap_t *pcmap,
	       psf_put_name_chars_proc_t put_name_chars,
	       const gs_const_string *alt_cmap_name, int font_index_only)
{
    const gs_const_string *const cmap_name =
	(alt_cmap_name ? alt_cmap_name : &pcmap->CMapName);
    const gs_cid_system_info_t *const pcidsi = pcmap->CIDSystemInfo;

    switch (pcmap->CMapType) {
    case 0: case 1: case 2:
	break;
    default:
	return_error(gs_error_rangecheck);
    }

    /* Write the header. */

    if (!pcmap->ToUnicode) {
	stream_puts(s, "%!PS-Adobe-3.0 Resource-CMap\n");
	stream_puts(s, "%%DocumentNeededResources: ProcSet (CIDInit)\n");
	stream_puts(s, "%%IncludeResource: ProcSet (CIDInit)\n");
	pput_string_entry(s, "%%BeginResource: CMap (", cmap_name);
	pput_string_entry(s, ")\n%%Title: (", cmap_name);
	pput_string_entry(s, " ", &pcidsi->Registry);
	pput_string_entry(s, " ", &pcidsi->Ordering);
	pprintd1(s, " %d)\n", pcidsi->Supplement);
	pprintg1(s, "%%%%Version: %g\n", pcmap->CMapVersion);
    }
    stream_puts(s, "/CIDInit /ProcSet findresource begin\n");
    stream_puts(s, "12 dict begin\nbegincmap\n");

    /* Write the fixed entries. */

    pprintd1(s, "/CMapType %d def\n", pcmap->CMapType);
    stream_puts(s, "/CMapName/");
    put_name_chars(s, cmap_name->data, cmap_name->size);
    stream_puts(s, " def\n");
    if (!pcmap->ToUnicode) {
	pprintg1(s, "/CMapVersion %g def\n", pcmap->CMapVersion);
	stream_puts(s, "/CIDSystemInfo");
	if (font_index_only >= 0 && font_index_only < pcmap->num_fonts) {
	    cmap_put_system_info(s, pcidsi + font_index_only);
	} else if (pcmap->num_fonts == 1) {
	    cmap_put_system_info(s, pcidsi);
	} else {
	    int i;

	    pprintd1(s, " %d array\n", pcmap->num_fonts);
	    for (i = 0; i < pcmap->num_fonts; ++i) {
		pprintd1(s, "dup %d", i);
		cmap_put_system_info(s, pcidsi + i);
		stream_puts(s, "put\n");
	    }
	}
	stream_puts(s, " def\n");
	if (uid_is_XUID(&pcmap->uid)) {
	    uint i, n = uid_XUID_size(&pcmap->uid);
	    const long *values = uid_XUID_values(&pcmap->uid);

	    stream_puts(s, "/XUID [");
	    for (i = 0; i < n; ++i)
		pprintld1(s, " %ld", values[i]);
	    stream_puts(s, "] def\n");
	}
	pprintld1(s, "/UIDOffset %ld def\n", pcmap->UIDOffset);
	pprintd1(s, "/WMode %d def\n", pcmap->WMode);
    }

    /* Write the code space ranges. */

    {
	gs_cmap_ranges_enum_t renum;
#define MAX_RANGES 100
	gx_code_space_range_t ranges[MAX_RANGES];
	int code, count = 0;

	for (gs_cmap_ranges_enum_init(pcmap, &renum);
	     (code = gs_cmap_enum_next_range(&renum)) == 0; ) {
	    if (count == MAX_RANGES) {
		cmap_put_ranges(s, ranges, count);
		count = 0;
	    }
	    ranges[count++] = renum.range;
	}
	if (code < 0)
	    return code;
	if (count)
	    cmap_put_ranges(s, ranges, count);
#undef MAX_RANGES
    }

    /* Write the code and notdef data. */

    {
	int code;

	code = cmap_put_code_map(mem, s, 1, pcmap, &cmap_notdef_operators,
			         put_name_chars, font_index_only);
	if (code < 0)
	    return code;
	code = cmap_put_code_map(mem, s, 0, pcmap, &cmap_cid_operators,
			         put_name_chars, font_index_only);
	if (code < 0)
	    return code;
    }

    /* Write the trailer. */

    stream_puts(s, "endcmap\n");
    stream_puts(s, "CMapName currentdict /CMap defineresource pop\nend end\n");
    if (!pcmap->ToUnicode) {
	stream_puts(s, "%%EndResource\n");
	stream_puts(s, "%%EOF\n");
    }

    return 0;
}
예제 #4
0
/*
 * Transition from string context to text context.
 */
static int
sync_text_state(gx_device_pdf *pdev)
{
    pdf_text_state_t *pts = pdev->text->text_state;
    stream *s = pdev->strm;
    int code;

    if (pts->buffer.count_chars == 0)
        return 0;		/* nothing to output */

    if (pts->continue_line)
        return flush_text_buffer(pdev);

    /* Bring text state parameters up to date. */

    if (pts->out.character_spacing != pts->in.character_spacing) {
        pprintg1(s, "%g Tc\n", pts->in.character_spacing);
        pts->out.character_spacing = pts->in.character_spacing;
    }

    if (pts->out.pdfont != pts->in.pdfont || pts->out.size != pts->in.size) {
        pdf_font_resource_t *pdfont = pts->in.pdfont;

        code = pdf_assign_font_object_id(pdev, pdfont);
        if (code < 0)
            return code;
        pprints1(s, "/%s ", pdfont->rname);
        pprintg1(s, "%g Tf\n", pts->in.size);
        pts->out.pdfont = pdfont;
        pts->out.size = pts->in.size;
        /*
         * In PDF, the only place to specify WMode is in the CMap
         * (a.k.a. Encoding) of a Type 0 font.
         */
        pts->wmode =
            (pdfont->FontType == ft_composite ?
             pdfont->u.type0.WMode : 0);
        code = pdf_used_charproc_resources(pdev, pdfont);
        if (code < 0)
            return code;
    }

    if (memcmp(&pts->in.matrix, &pts->out.matrix, sizeof(pts->in.matrix)) ||
         ((pts->start.x != pts->out_pos.x || pts->start.y != pts->out_pos.y) &&
          (pts->buffer.count_chars != 0 || pts->buffer.count_moves != 0))) {
        /* pdf_set_text_matrix sets out.matrix = in.matrix */
        code = pdf_set_text_matrix(pdev);
        if (code < 0)
            return code;
    }

    if (pts->out.render_mode != pts->in.render_mode) {
        pprintg1(s, "%g Tr\n", pts->in.render_mode);
        pts->out.render_mode = pts->in.render_mode;
    }

    if (pts->out.word_spacing != pts->in.word_spacing) {
        if (memchr(pts->buffer.chars, 32, pts->buffer.count_chars)) {
            pprintg1(s, "%g Tw\n", pts->in.word_spacing);
            pts->out.word_spacing = pts->in.word_spacing;
        }
    }

    return flush_text_buffer(pdev);
}
예제 #5
0
static int
param_print_typed(gs_param_list * plist, gs_param_name pkey,
                  gs_param_typed_value * pvalue)
{
    printer_param_list_t *const prlist = (printer_param_list_t *)plist;
    stream *s = prlist->strm;

    if (!prlist->any) {
        if (prlist->params.prefix)
            stream_puts(s, prlist->params.prefix);
        prlist->any = true;
    }
    if (prlist->params.item_prefix)
        stream_puts(s, prlist->params.item_prefix);
    pprints1(s, "/%s", pkey);
    switch (pvalue->type) {
        case gs_param_type_null:
            stream_puts(s, " null");
            break;
        case gs_param_type_bool:
            stream_puts(s, (pvalue->value.b ? " true" : " false"));
            break;
        case gs_param_type_int:
            pprintd1(s, " %d", pvalue->value.i);
            break;
        case gs_param_type_long:
            pprintld1(s, " %l", pvalue->value.l);
            break;
        case gs_param_type_float:
            pprintg1(s, " %g", pvalue->value.f);
            break;
        case gs_param_type_string:
            s_write_ps_string(s, pvalue->value.s.data, pvalue->value.s.size,
                              prlist->params.print_ok);
            break;
        case gs_param_type_name:
            /****** SHOULD USE #-ESCAPES FOR PDF ******/
            stream_putc(s, '/');
            stream_write(s, pvalue->value.n.data, pvalue->value.n.size);
            break;
        case gs_param_type_int_array:
            {
                uint i;
                char sepr = (pvalue->value.ia.size <= 10 ? ' ' : '\n');

                stream_putc(s, '[');
                for (i = 0; i < pvalue->value.ia.size; ++i) {
                    pprintd1(s, "%d", pvalue->value.ia.data[i]);
                    stream_putc(s, sepr);
                }
                stream_putc(s, ']');
            }
            break;
        case gs_param_type_float_array:
            {
                uint i;
                char sepr = (pvalue->value.fa.size <= 10 ? ' ' : '\n');

                stream_putc(s, '[');
                for (i = 0; i < pvalue->value.fa.size; ++i) {
                    pprintg1(s, "%g", pvalue->value.fa.data[i]);
                    stream_putc(s, sepr);
                }
                stream_putc(s, ']');
            }
            break;
            /*case gs_param_type_string_array: */
            /*case gs_param_type_name_array: */
        default:
            return_error(gs_error_typecheck);
    }
    if (prlist->params.item_suffix)
        stream_puts(s, prlist->params.item_suffix);
    return 0;
}
예제 #6
0
const char *
pprintg3(stream * s, const char *format, floatp v1, floatp v2, floatp v3)
{
    return pprintg2(s, pprintg1(s, format, v1), v2, v3);
}