Exemple #1
0
pdc_id
pdc_begin_obj(pdc_output *out, pdc_id obj_id)
{
    if (obj_id == PDC_NEW_ID)
	obj_id = pdc_alloc_id(out);

    out->file_offset[obj_id] = pdc_tell_out(out);
    pdc_printf(out, "%ld 0 obj\n", obj_id);

    return obj_id;
}
Exemple #2
0
void
pdf_write_colormap(PDF *p, int slot)
{
    PDF_data_source src;
    pdf_colorspace *cs, *base;
    pdc_id length_id;

    cs   = &p->colorspaces[slot];

    if (cs->type != Indexed || cs->val.indexed.colormap_done == pdc_true)
	return;

    base = &p->colorspaces[cs->val.indexed.base];

    pdc_begin_obj(p->out, cs->val.indexed.colormap_id);	/* colormap object */
    pdc_begin_dict(p->out);

    if (pdc_get_compresslevel(p->out))
	pdc_puts(p->out, "/Filter/FlateDecode\n");

    /* Length of colormap object */
    length_id = pdc_alloc_id(p->out);
    pdc_objref(p->out, "/Length", length_id);
    pdc_end_dict(p->out);

    src.init		= NULL;
    src.fill		= pdf_data_source_buf_fill;
    src.terminate	= NULL;

    src.buffer_start	= (unsigned char *) cs->val.indexed.colormap;

    src.buffer_length = (size_t) (cs->val.indexed.palette_size *
				pdf_color_components(p, cs->val.indexed.base));

    src.bytes_available = 0;
    src.next_byte	= NULL;

    /* Write colormap data */
    pdf_copy_stream(p, &src, pdc_true);	/* colormap data */

    pdc_end_obj(p->out);				/* colormap object */

    pdc_put_pdfstreamlength(p->out, length_id);

    /* free the colormap now that it's written */
    pdc_free(p->pdc, cs->val.indexed.colormap);
    cs->val.indexed.colormap = NULL;
    cs->val.indexed.colormap_done = pdc_true;
} /* pdf_write_colormap */
Exemple #3
0
void
pdf__end_font(PDF *p)
{
    int i;
    pdc_t3font *t3font;

    PDF_SET_STATE(p, pdf_state_document);

    t3font = p->t3font;

    t3font->charprocs_id = pdc_alloc_id(p->out);
    pdc_begin_obj(p->out, t3font->charprocs_id);        /* CharProcs dict */
    pdc_begin_dict(p->out);

    for (i = 0; i < t3font->next_glyph; i++) {
        pdc_put_pdfname(p->out,
            t3font->glyphs[i].name, strlen(t3font->glyphs[i].name));
        pdc_printf(p->out, " %ld 0 R\n", t3font->glyphs[i].charproc_id);
    }

    pdc_end_dict(p->out);
    pdc_end_obj(p->out);                        /* CharProcs dict */

    pdc_begin_obj(p->out, t3font->res_id);
    pdc_begin_dict(p->out);                     /* Resource dict */

    pdf_write_page_fonts(p);                    /* Font resources */

    pdf_write_page_colorspaces(p);              /* Color space resources */

    pdf_write_page_pattern(p);                  /* Pattern resources */

    pdf_write_xobjects(p);                      /* XObject resources */

    pdc_end_dict(p->out);                       /* Resource dict */
    pdc_end_obj(p->out);                        /* Resource object */

    p->t3font = (pdc_t3font *) NULL;

    if (p->flush & pdf_flush_content)
        pdc_flush_stream(p->out);
}
Exemple #4
0
static int
pdf_insert_bookmark(
    PDF *p,
    const char *hypertext,
    pdf_outline *outline,
    int jndex)
{
    static const char fn[] = "pdf_insert_bookmark";
    pdf_outline *root, *self;
    int parent;
    int self_idx;
    int pageno = pdf_current_page(p);

    /* allocation */
    if (p->outline_count == 0)
    {
        p->outline_capacity = OUTLINE_CHUNKSIZE;
        p->outlines = (pdf_outline *) pdc_calloc(p->pdc,
                          sizeof(pdf_outline) * p->outline_capacity, fn);

        /* populate the root outline object */
        root = &p->outlines[0];
        pdf_init_outline(p, root);
        root->obj_id = pdc_alloc_id(p->out);
        root->open = pdc_true;

        /* set the open mode show bookmarks if we have at least one,
         * and the client didn't already set his own open mode.
         */
        pdf_fix_openmode(p);
    }
    else if (p->outline_count + 1 >= p->outline_capacity)
    {
        p->outline_capacity *= 2;
        p->outlines = (pdf_outline *) pdc_realloc(p->pdc, p->outlines,
                          sizeof(pdf_outline) * p->outline_capacity, fn);
    }

    /* copy */
    self_idx = ++p->outline_count;
    self = &p->outlines[self_idx];
    memcpy(self, outline, sizeof(pdf_outline));

    self->obj_id = pdc_alloc_id(p->out);
    self->text = (char *) hypertext;
    self->page_id = pdf_get_page_id(p, 0);
    parent = self->parent;

    /* default destination */
    if (self->action == NULL && self->dest == NULL)
        self->dest = pdf_init_destination(p);

    /* no destination */
    if (self->dest != NULL &&
        self->dest->name != NULL && !strlen(self->dest->name))
    {
        pdf_cleanup_destination(p, self->dest);
        self->dest = NULL;
    }

    /* current page */
    if (self->dest)
    {
	/* this ugly code is for compatibility with the
	** obsolete "bookmarkdest" parameter.
	*/
        if (self->dest->pgnum == 0)
            self->dest->pgnum = pdf_current_page(p);

        if (self->dest->pgnum == 0)
	{
            self->dest->pgnum = 1;
	}
	else if (self->dest->page == PDC_BAD_ID)
	{
            self->dest->page = pdf_get_page_id(p, self->dest->pgnum);
	}
    }

    /* special case: empty list.
    */
    if (FIRST(parent) == 0)
    {
        if (jndex > 0)
	    pdc_error(p->pdc, PDC_E_OPT_ILLINTEGER, "index",
                pdc_errprintf(p->pdc, "%d", jndex), 0, 0);

        FIRST(parent) = LAST(parent) = self_idx;
	self->in_order = pdc_true;
    }
    else switch (jndex)
    {
	case -2:	/* insert "in order" */
	{
	    /* the "natural" case: append to the end if appropriate.
	    */
	    if (pageno >= search_backward(p, -1, LAST(parent)))
	    {
		self->prev = LAST(parent);
		NEXT(LAST(parent)) = self_idx;
		LAST(parent) = self_idx;
	    }
	    else
	    {
		int idx;
		int curr_pg = 1;
		int next_pg;

		for (idx = FIRST(parent); idx != 0; idx = NEXT(idx))
		{
		    if (!IN_ORDER(idx))
			continue;

		    next_pg = pdf_search_page_fwd(p, curr_pg, PAGE_ID(idx));

		    /* TODO: understand why this can happen.
		    */
		    if (next_pg < 1)
		    {
			idx = 0;
			break;
		    }

		    if (next_pg > pageno)
		    {
			self->next = idx;
			self->prev = PREV(idx);
			PREV(idx) = self_idx;

			if (self->prev == 0)
			    FIRST(parent) = self_idx;
			else
			    NEXT(self->prev) = self_idx;

			break;
		    }

		    curr_pg = next_pg;
		}

		/* if there are no "in order" bookmarks yet,
		** we simply append this one to the end.
		*/
		if (idx == 0)
		{
		    self->prev = LAST(parent);
		    NEXT(LAST(parent)) = self_idx;
		    LAST(parent) = self_idx;
		}
	    }

	    self->in_order = pdc_true;
	    break;
	}

	case -1:	/* append to the end */
	{
	    self->prev = LAST(parent);
	    NEXT(LAST(parent)) = self_idx;
	    LAST(parent) = self_idx;

	    self->in_order =
		(pageno >= search_backward(p, pageno, self->prev));
	    break;
	}

	case 0:		/* insert at the beginning */
	{
	    self->next = FIRST(parent);
	    PREV(FIRST(parent)) = self_idx;
	    FIRST(parent) = self_idx;

	    self->in_order =
		(pageno <= search_forward(p, pageno, self->next));
	    break;
	}

	default:	/* insert before [1..LAST] */
	{
	    int i;
	    int target = FIRST(parent);

            for (i = 0; i < jndex; ++i)
	    {
		if (target == LAST(parent))
		    pdc_error(p->pdc, PDC_E_OPT_ILLINTEGER, "index",
                        pdc_errprintf(p->pdc, "%d", jndex), 0, 0);

		target = NEXT(target);
	    }

	    self->next = target;
	    self->prev = PREV(target);
	    NEXT(self->prev) = PREV(self->next) = self_idx;

	    self->in_order =
		((pageno >= search_backward(p, pageno, self->prev)) &&
		(pageno <= search_forward(p, pageno, self->next)));
	    break;
	}
    } /* else switch */

    /* increase the number of open sub-entries for all relevant ancestors */
    do {
        COUNT(parent)++;
    } while (OPEN(parent) && (parent = PARENT(parent)) != 0);

    return (self_idx);          /* caller may use this as handle */
}
Exemple #5
0
int
pdf_add_colorspace(PDF *p, pdf_colorspace *cs, pdc_bool inuse)
{
    pdf_colorspace *cs_new;
    static const char fn[] = "pdf_add_colorspace";
    int slot;

    for (slot = 0; slot < p->colorspaces_number; slot++)
    {
	if (pdf_colorspace_equal(p, &p->colorspaces[slot], cs))
	{
	    if (inuse)
		p->colorspaces[slot].used_on_current_page = pdc_true;
	    return slot;
	}
    }

    slot = p->colorspaces_number;

    if (p->colorspaces_number >= p->colorspaces_capacity)
	pdf_grow_colorspaces(p);

    cs_new = &p->colorspaces[slot];

    cs_new->type = cs->type;

    /* don't allocate id for simple color spaces, since we don't write these */
    if (PDF_SIMPLE_COLORSPACE(cs)) {
	cs_new->obj_id = PDC_BAD_ID;
	cs_new->used_on_current_page = pdc_false;

    } else {
	cs_new->obj_id = pdc_alloc_id(p->out);
	cs_new->used_on_current_page = inuse;
    }

    switch (cs_new->type) {
	case DeviceGray:
	case DeviceRGB:
	case DeviceCMYK:
	break;


	case Indexed:
	{
	size_t palsize; 	/* palette size in bytes */

	palsize = cs->val.indexed.palette_size *
			    pdf_color_components(p, cs->val.indexed.base);

        cs_new->val.indexed.base = cs->val.indexed.base;
        cs_new->val.indexed.palette_size = cs->val.indexed.palette_size;
        cs_new->val.indexed.colormap_id = pdc_alloc_id(p->out);
        cs_new->val.indexed.colormap =
	    (pdf_colormap *) pdc_malloc(p->pdc, palsize, fn);
        memcpy(cs_new->val.indexed.colormap, cs->val.indexed.colormap, palsize);
        cs_new->val.indexed.colormap_done = pdc_false;
	break;

	case PatternCS:
        cs_new->val.pattern.base = cs->val.pattern.base;
	break;
	}


	default:
	    pdc_error(p->pdc, PDF_E_INT_BADCS, fn,
		pdc_errprintf(p->pdc, "%d", slot),
		pdc_errprintf(p->pdc, "%d", cs_new->type), 0);
    }

    p->colorspaces_number++;

    return slot;
} /* pdf_add_colorspace */
Exemple #6
0
/* Start a new pattern definition. */
int
pdf__begin_pattern(
    PDF *p,
    pdc_scalar width,
    pdc_scalar height,
    pdc_scalar xstep,
    pdc_scalar ystep,
    int painttype)
{
    int slot = -1;

    pdc_check_number_limits(p->pdc, "width", width,
                            PDC_FLOAT_PREC, PDC_FLOAT_MAX);
    pdc_check_number_limits(p->pdc, "height", height,
                            PDC_FLOAT_PREC, PDC_FLOAT_MAX);

    pdc_check_number_zero(p->pdc, "xstep", xstep);
    pdc_check_number_zero(p->pdc, "ystep", ystep);

    if (painttype != 1 && painttype != 2)
	pdc_error(p->pdc, PDC_E_ILLARG_INT,
	    "painttype", pdc_errprintf(p->pdc, "%d", painttype), 0, 0);

    if (p->pattern_number == p->pattern_capacity)
	pdf_grow_pattern(p);

    pdf_pg_suspend(p);
    PDF_SET_STATE(p, pdf_state_pattern);

    p->pattern[p->pattern_number].obj_id = pdc_begin_obj(p->out, PDC_NEW_ID);
    p->pattern[p->pattern_number].painttype = painttype;

    pdc_begin_dict(p->out);				/* pattern dict*/

    p->res_id = pdc_alloc_id(p->out);

    pdc_puts(p->out, "/PatternType 1\n");		/* tiling pattern */

    /* colored or uncolored pattern */
    pdc_printf(p->out, "/PaintType %d\n", painttype);
    pdc_puts(p->out, "/TilingType 1\n");		/* constant spacing */

    pdc_printf(p->out, "/BBox[0 0 %f %f]\n", width, height);

    pdc_printf(p->out, "/XStep %f\n", xstep);
    pdc_printf(p->out, "/YStep %f\n", ystep);

    pdc_objref(p->out, "/Resources", p->res_id);

    p->length_id = pdc_alloc_id(p->out);
    pdc_objref(p->out, "/Length", p->length_id);

    if (pdc_get_compresslevel(p->out))
	pdc_puts(p->out, "/Filter/FlateDecode\n");

    pdc_end_dict(p->out);				/* pattern dict*/
    pdc_begin_pdfstream(p->out);

    slot = p->pattern_number;
    p->pattern_number++;

    /* top-down y-coordinates */
    pdf_set_topdownsystem(p, height);

    /* set color differing from PDF default */
    pdf_set_default_color(p, pdc_false);

    if (!p->pdc->smokerun)
        pdc_logg_cond(p->pdc, 1, trc_api, "[Begin pattern %d]\n", slot);

    return slot;
}
Exemple #7
0
/* returns font handle,
** or -1 if no font found,
** or -2 in case of an error.
*/
int
pdf_handle_cidfont(PDF *p, const char *fontname, const char *encoding)
{
    pdc_font *font = &p->fonts[p->fonts_number];
    int slot, cmap, metric;

    /*
     * Look whether font is already in the cache.
     * If font with same name and encoding is found,
     * return its descriptor.
     */

    for (slot = 0; slot < p->fonts_number; slot++) {
        if (p->fonts[slot].encoding == pdc_cid &&
            p->fonts[slot].style == font->style &&
            !strcmp(p->fonts[slot].name, fontname) &&
            !strcmp(p->fonts[slot].cmapname, encoding))
            return slot;
    }

    /* Check the requested CMap */
    for (cmap = 0; cmap < NUMBER_OF_CMAPS; cmap++)
        if (!strcmp(cmaps[cmap].name, encoding))
            break;

    /* Unknown CMap */
    if (cmap == NUMBER_OF_CMAPS)
        return -1;

    /* Check whether this CMap is supported in the desired PDF version */
    if (cmaps[cmap].compatibility > p->compatibility)
    {
	pdc_set_errmsg(p->pdc, PDF_E_DOC_PDFVERSION,
	    encoding, pdc_errprintf(p->pdc, "%d.%d",
	    p->compatibility/10, p->compatibility % 10), 0, 0);

        if (font->verbose)
            pdc_error(p->pdc, -1, 0, 0, 0, 0);

        return -2;
    }

    /* Check whether the font name is among the known CID fonts */
    for (metric = 0; metric < SIZEOF_CID_METRICS; metric++) {
        if (!strcmp(pdf_cid_metrics[metric].name, fontname))
            break;
    }

    /* Unknown font */
    if (metric == SIZEOF_CID_METRICS)
    {
	pdc_set_errmsg(p->pdc, PDF_E_CJK_NOSTANDARD, fontname, 0, 0, 0);

        if (font->verbose)
            pdc_error(p->pdc, -1, 0, 0, 0, 0);

        return -2;
    }

    /* Selected CMap and font don't match */
    if (cmaps[cmap].charcoll != cc_identity &&
        cmaps[cmap].charcoll != pdf_cid_metrics[metric].charcoll)
    {
	pdc_set_errmsg(p->pdc, PDF_E_FONT_BADENC, fontname, encoding, 0, 0);

        if (font->verbose)
            pdc_error(p->pdc, -1, 0, 0, 0, 0);

        return -2;
    }

    /* For Unicode capable language wrappers only UCS2 CMaps allowed */
    if (cmaps[cmap].codesize == 0 && p->textformat == pdc_auto2)
    {
	pdc_set_errmsg(p->pdc, PDF_E_FONT_NEEDUCS2, encoding, fontname, 0, 0);

        if (font->verbose)
            pdc_error(p->pdc, -1, 0, 0, 0, 0);

        return -2;
    }

    p->fonts_number++;

    /* Code size of CMap */
    font->codeSize = 0;
    font->numOfCodes = 0;

    /* Fill up the font struct */
    pdc_fill_font_metric(p->pdc, font, &pdf_cid_metrics[metric]);

    /* Now everything is fine; fill the remaining entries */
    font->encoding = pdc_cid;
    font->cmapname = pdc_strdup(p->pdc, encoding);
    font->ttname = pdc_strdup(p->pdc, fontname);
    font->apiname = pdc_strdup(p->pdc, fontname);
    font->obj_id = pdc_alloc_id(p->out);
    font->embedding = pdc_false;
    font->kerning = pdc_false;
    font->subsetting = pdc_false;
    font->autocidfont = pdc_false;
    font->unicodemap = pdc_false;
    font->autosubsetting = pdc_false;

    /* return valid font descriptor */
    return slot;
}
Exemple #8
0
void
pdf__begin_glyph(
    PDF *p,
    const char *glyphname,
    pdc_scalar wx,
    pdc_scalar llx, pdc_scalar lly, pdc_scalar urx, pdc_scalar ury)
{
    static const char fn[] = "pdf__begin_glyph";
    pdf_font *font;
    pdf_t3font *t3font;
    pdf_t3glyph *glyph = NULL;
    pdc_scalar tbc;
    int ig;

    if (glyphname == NULL || *glyphname == '\0')
        pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "glyphname", 0, 0, 0);

    font = &p->fonts[p->t3slot];
    t3font = font->t3font;

    /* error message prefix */
    pdc_push_errmsg(p->pdc, PDF_E_T3_FONT_PREFIX, font->apiname, 0, 0, 0);

    for (ig = 0; ig < t3font->next_glyph; ig++)
    {
        glyph = &t3font->glyphs[ig];
        if (!pdc_strcmp(glyph->name, glyphname))
        {
            if (t3font->pass == glyph->pass)
                pdc_error(p->pdc, PDF_E_T3_GLYPH, glyphname, 0, 0, 0);
            else
                break;
        }
    }

    /* new glyph */
    if (ig == t3font->next_glyph)
    {
        if (t3font->pass == 2)
            pdc_error(p->pdc, PDF_E_T3_UNKOWNGLYPH, glyphname, 0, 0, 0);

        pdc_check_number(p->pdc, "wx", wx);
        pdc_check_number(p->pdc, "llx", llx);
        pdc_check_number(p->pdc, "lly", lly);
        pdc_check_number(p->pdc, "urx", urx);
        pdc_check_number(p->pdc, "ury", ury);

        if (t3font->colorized == pdc_true &&
            (llx != 0 || lly != 0 ||
             urx != 0 || ury != 0))
            pdc_error(p->pdc, PDF_E_T3_BADBBOX, 0, 0, 0, 0);


        if (urx < llx)
        {
            tbc = llx;
            llx = urx;
            urx = tbc;
        }

        if (ury < lly)
        {
            tbc = lly;
            lly = ury;
            ury = tbc;
        }

        if (ig == t3font->capacity)
        {
            t3font->capacity *= 2;
            t3font->glyphs = (pdf_t3glyph *) pdc_realloc(p->pdc, t3font->glyphs,
                t3font->capacity * sizeof (pdf_t3glyph), fn);
        }

        glyph = &t3font->glyphs[ig];
        glyph->charproc_id = PDC_BAD_ID;
        glyph->name = pdc_strdup(p->pdc, glyphname);
        glyph->wx = wx;
        glyph->llx = llx;
        glyph->lly = lly;
        glyph->urx = urx;
        glyph->ury = ury;

        /* see comment in p_font.c for explanation */
        glyph->width = 1000 * wx * font->ft.matrix.a;

        /* if the strdup above fails, cleanup won't touch this slot. */
        t3font->next_glyph++;
    }
    glyph->pass = t3font->pass;
    t3font->curr_glyph = ig;

    pdc_logg_cond(p->pdc, 1, trc_font,
        "\tBegin of Type3 font glyph \"%s\"\n", glyphname);

    if (t3font->pass != 1)
    {
            if (t3font->pass == 2)
                pdc_logg_cond(p->pdc, 2, trc_font,
                              "\t\tglyph [%d] was used in text\n", ig);

            glyph->charproc_id = pdc_begin_obj(p->out, PDC_NEW_ID);
            pdc_begin_dict(p->out);

            p->length_id = pdc_alloc_id(p->out);
            pdc_objref(p->out, "/Length", p->length_id);

            if (pdc_get_compresslevel(p->out))
                pdc_puts(p->out, "/Filter/FlateDecode\n");

            pdc_end_dict(p->out);

            pdc_begin_pdfstream(p->out);

            if (t3font->colorized == pdc_true)
                pdc_printf(p->out, "%f 0 d0\n", glyph->wx);
            else
            {
                pdc_printf(p->out, "%f 0 %f %f %f %f d1\n",
                    glyph->wx, glyph->llx, glyph->lly, glyph->urx, glyph->ury);

                /* adjust the font's bounding box */
                if (glyph->llx < font->ft.bbox.llx)
                    font->ft.bbox.llx = glyph->llx;
                if (glyph->lly < font->ft.bbox.lly)
                    font->ft.bbox.lly = glyph->lly;
                if (glyph->urx > font->ft.bbox.urx)
                    font->ft.bbox.urx = glyph->urx;
                if (glyph->ury > font->ft.bbox.ury)
                    font->ft.bbox.ury = glyph->ury;
            }

            /* we must initialize the text, graphics and color state
             * otherwise the user get unpredictable appearance of a
             * glyph because of optimizing outputting graphics properties.
             * Following statements were inserted due to bug #719
             */
            pdf_init_tstate(p);
            pdf_init_gstate(p);
            pdf_init_cstate(p);

            PDF_SET_STATE(p, pdf_state_glyph);
    }
    else
    {
        PDF_SET_STATE(p, pdf_state_glyphmetrics);
    }

    pdc_pop_errmsg(p->pdc);

    if (!p->pdc->smokerun)
        pdc_logg_cond(p->pdc, 1, trc_api, "[Begin glyph %d]\n", ig);
}
Exemple #9
0
void
pdf__end_font(PDF *p)
{
    int ig;
    pdf_font *font;
    pdf_t3font *t3font;

    PDF_SET_STATE(p, pdf_state_document);

    font = &p->fonts[p->t3slot];
    t3font = font->t3font;

    /* error message prefix */
    pdc_push_errmsg(p->pdc, PDF_E_T3_FONT_PREFIX, font->apiname, 0, 0, 0);

    if (t3font->pass == 0)
    {
        pdf_t3glyph glyph0 = t3font->glyphs[0];

        /* search for .notdef glyph */
        if (pdc_strcmp(glyph0.name, (char *) pdc_get_notdef_glyphname()))
        {
            for (ig = 0; ig < t3font->next_glyph; ig++)
            {
                if (!pdc_strcmp(t3font->glyphs[ig].name,
                                (char *) pdc_get_notdef_glyphname()))
                    break;
            }

            if (ig < t3font->next_glyph)
            {
                pdc_logg_cond(p->pdc, 2, trc_font,
                    "\tGlyph id %d: \"%s\" will be exchanged "
                    "with glyph id 0: \"%s\"\n",
                    ig, t3font->glyphs[ig].name, glyph0.name);

                t3font->glyphs[0] = t3font->glyphs[ig];
                t3font->glyphs[ig] = glyph0;
            }
            else
            {
                pdc_warning(p->pdc, PDF_E_T3_MISSNOTDEF, 0, 0, 0, 0);
            }
        }
    }

    if (t3font->pass != 1)
    {
        t3font->charprocs_id = pdc_alloc_id(p->out);
        pdc_begin_obj(p->out, t3font->charprocs_id); /* CharProcs dict */
        pdc_begin_dict(p->out);

        for (ig = 0; ig < t3font->next_glyph; ig++)
        {
            pdf_t3glyph *glyph = &t3font->glyphs[ig];

            if (glyph->charproc_id != PDC_BAD_ID)
            {
                pdf_put_pdfname(p, glyph->name);
                pdc_objref(p->out, "", glyph->charproc_id);
            }
        }

        pdc_end_dict(p->out);
        pdc_end_obj(p->out);                        /* CharProcs dict */

        pdc_begin_obj(p->out, t3font->res_id);
        pdc_begin_dict(p->out);                     /* Resource dict */

        pdf_write_page_fonts(p);                    /* Font resources */

        pdf_write_page_colorspaces(p);              /* Color space resources */

        pdf_write_page_pattern(p);                  /* Pattern resources */

        pdf_write_xobjects(p);                      /* XObject resources */

        pdc_end_dict(p->out);                       /* Resource dict */
        pdc_end_obj(p->out);                        /* Resource object */

        pdf_pg_resume(p, -1);

        if (p->flush & pdc_flush_content)
            pdc_flush_stream(p->out);

        /* see pdf__begin_glyph */
        pdf_init_tstate(p);
        pdf_init_gstate(p);
        pdf_init_cstate(p);
    }

    pdc_logg_cond(p->pdc, 1, trc_font,
        "\tEnd of Type3 font \"%s\"\n", font->apiname);

    pdc_pop_errmsg(p->pdc);

    if (!p->pdc->smokerun)
        pdc_logg_cond(p->pdc, 1, trc_api, "[End font %d]\n", p->t3slot);

    p->t3slot = -1;
}
Exemple #10
0
void
pdf__begin_font(
    PDF *p,
    const char *fontname, int len,
    pdc_scalar a, pdc_scalar b, pdc_scalar c, pdc_scalar d,
    pdc_scalar e, pdc_scalar f,
    const char *optlist)
{
    static const char fn[] = "pdf__begin_font";
    pdc_resopt *results;
    pdf_font tmpfont, *font;
    pdf_font_options fo;
    pdc_scalar det;
    pdc_clientdata cdata;
    int colorized = pdc_false;
    int metricsonly = pdc_false;
    int slot;

    if (fontname == NULL)
        pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0);

    /* Converting fontname */
    fontname = pdf_convert_name(p, fontname, len,
                                PDC_CONV_WITHBOM | PDC_CONV_TMPALLOC);
    if (fontname == NULL || *fontname == '\0')
        pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "fontname", 0, 0, 0);

    pdc_logg_cond(p->pdc, 1, trc_font,
        "\tBegin of Type3 font \"%s\"\n", fontname);

    /* error message prefix */
    pdc_push_errmsg(p->pdc, PDF_E_T3_FONT_PREFIX, fontname, 0, 0, 0);

    /* look for an already existing font */
    for (slot = 0; slot < p->fonts_number; slot++)
    {
        if (!pdc_strcmp(p->fonts[slot].apiname, fontname))
        {
            if (p->fonts[slot].t3font->pass == 1)
            {
                pdc_logg_cond(p->pdc, 1, trc_font,
                    "\tType3 font [%d] with metric definition found\n", slot);

                PDF_CHECK_STATE(p, pdf_state_document);

                p->fonts[slot].t3font->pass = 2;
                p->t3slot = slot;

                pdc_pop_errmsg(p->pdc);

                pdf_pg_suspend(p);
                PDF_SET_STATE(p, pdf_state_font);
                return;
            }

            pdc_error(p->pdc, PDF_E_T3_FONTEXISTS, 0, 0, 0, 0);
        }
    }

    pdc_check_number(p->pdc, "a", a);
    pdc_check_number(p->pdc, "b", b);
    pdc_check_number(p->pdc, "c", c);
    pdc_check_number(p->pdc, "d", d);
    pdc_check_number(p->pdc, "e", e);
    pdc_check_number(p->pdc, "f", f);

    det = a*d - b*c;

    if (det == 0)
        pdc_error(p->pdc, PDC_E_ILLARG_MATRIX,
            pdc_errprintf(p->pdc, "%f %f %f %f %f %f", a, b, c, d, e, f),
            0, 0, 0);

    /* parsing optlist */
    pdf_set_clientdata(p, &cdata);
    results = pdc_parse_optionlist(p->pdc, optlist, pdf_begin_font_options,
                                   &cdata, pdc_true);

    pdc_get_optvalues("colorized", results, &colorized, NULL);
    pdc_get_optvalues("widthsonly", results, &metricsonly, NULL);


    pdc_cleanup_optionlist(p->pdc, results);

    /* initialize font struct */
    font = &tmpfont;
    pdf_init_font_options(p, &fo);
    pdf_init_font(p, font, &fo);

    /*
     * We store the new font in a font slot marked with "invalidenc" encoding.
     * When the font is used for the first time we modify the encoding.
     * Later uses will make a copy if the encoding is different.
     */

    /* API font name */
    font->apiname = pdc_strdup(p->pdc, fontname);

    font->ft.m.type = fnt_Type3;
    font->hasoriginal = pdc_true;

    font->ft.matrix.a = a;
    font->ft.matrix.b = b;
    font->ft.matrix.c = c;
    font->ft.matrix.d = d;
    font->ft.matrix.e = e;
    font->ft.matrix.f = f;

    font->t3font = (pdf_t3font*) pdc_malloc(p->pdc, sizeof(pdf_t3font), fn);
    pdf_init_t3font(p, font->t3font, T3GLYPHS_CHUNKSIZE);

    font->t3font->colorized = colorized;


    /* the resource id is needed until the font dict is written */
    font->t3font->res_id = pdc_alloc_id(p->out);

    /* Now everything is fine, insert Type3 font with invalid encoding */
    slot = pdf_insert_font(p, font);

    /*
     * We must store a pointer to the current font because its glyph
     * definitions may use other fonts and we would be unable to find
     * "our" current font again. This pointer lives throughout the
     * font definition, and will be reset in PDF_end_font() below.
     */
    p->t3slot = slot;

    if (metricsonly)
    {
        font->t3font->pass = 1;
        pdc_logg_cond(p->pdc, 2, trc_font,
                          "\t\tonly for metric definition\n");
    }
    else
    {
        pdf_pg_suspend(p);
    }

    pdc_pop_errmsg(p->pdc);

    PDF_SET_STATE(p, pdf_state_font);

    if (!p->pdc->smokerun)
        pdc_logg_cond(p->pdc, 1, trc_api, "[Begin font %d]\n", p->t3slot);
}
Exemple #11
0
int
pdf__create_gstate(PDF *p, const char *optlist)
{
    pdf_extgstateresource *gs;
    int slot = -1;
    int font = pdc_undef;
    int inum;
    pdc_clientdata data;
    pdc_resopt *results;

    if (optlist == NULL || !*optlist)
        pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "optlist", 0, 0, 0);

    slot = p->extgstates_number;
    if (slot == p->extgstates_capacity)
        pdf_grow_extgstates(p);

    p->extgstates_number++;
    gs = &p->extgstates[slot];
    gs->obj_id = pdc_alloc_id(p->out);

    /* parsing optlist */
    pdf_set_clientdata(p, &data);
    results = pdc_parse_optionlist(p->pdc, optlist, pdf_create_gstate_options,
                                   &data, pdc_true);

    pdc_get_optvalues("alphaisshape", results, &gs->alpha_is_shape, NULL);

    if (pdc_get_optvalues("blendmode", results, &inum, NULL))
        gs->blendmode = (pdf_blendmode) inum;

    gs->dash_count = pdc_get_optvalues("dasharray", results, NULL, NULL);
    gs->dash_array = (pdc_scalar *) pdc_save_lastopt(results, PDC_OPT_SAVEALL);

    pdc_get_optvalues("dashphase", results, &gs->dash_phase, NULL);

    pdc_get_optvalues("flatness", results, &gs->flatness, NULL);

    pdc_get_optvalues("font", results, &font, NULL);
    if (font != pdc_undef)
        gs->font_obj = p->fonts[font].obj_id;

    pdc_get_optvalues("fontsize", results, &gs->font_size, NULL);

    pdc_get_optvalues("linecap", results, &gs->line_cap, NULL);

    pdc_get_optvalues("linejoin", results, &gs->line_join, NULL);

    pdc_get_optvalues("linewidth", results, &gs->line_width, NULL);

    pdc_get_optvalues("miterlimit", results, &gs->miter_limit, NULL);

    pdc_get_optvalues("opacityfill", results, &gs->opacity_fill, NULL);

    pdc_get_optvalues("opacitystroke", results, &gs->opacity_stroke, NULL);

    pdc_get_optvalues("overprintfill", results, &gs->overprint_fill, NULL);

    pdc_get_optvalues("overprintmode", results, &gs->overprint_mode, NULL);

    pdc_get_optvalues("overprintstroke", results, &gs->overprint_stroke, NULL);

    if (pdc_get_optvalues("renderingintent", results, &inum, NULL))
        gs->ri = (pdf_renderingintent) inum;

    pdc_get_optvalues("smoothness", results, &gs->smoothness, NULL);

    pdc_get_optvalues("strokeadjust", results, &gs->stroke_adjust, NULL);

    pdc_get_optvalues("textknockout", results, &gs->text_knockout, NULL);

    pdc_cleanup_optionlist(p->pdc, results);



    return slot;
}
Exemple #12
0
int
pdf_handle_t3font(PDF *p, const char *fontname, pdc_encoding enc, int oldslot)
{
    static const char fn[] = "pdf_handle_t3font";
    char *fname;
    int slot, i;
    unsigned int namlen;
    pdc_font *oldfont, *newfont;
    pdc_encodingvector *ev = p->encodings[enc].ev;

    oldfont = &p->fonts[oldslot];

    /* slot of new font struct - initialized in pdf__load_font */
    slot = p->fonts_number;
    newfont = &p->fonts[slot];

    /* font name incl. encoding name */
    namlen = strlen(fontname) + (int) strlen(ev->apiname) + 2;
    fname = (char *) pdc_malloc(p->pdc, namlen, fn);
    sprintf(fname, "%s.%s", fontname, ev->apiname);

    /*
     * This is a fresh font which has never been used.
     * Enter the new encoding, and we're done.
     */
    if (oldfont->encoding == pdc_invalidenc) {

        oldfont->encoding = enc;

        for (i = 0; i < oldfont->numOfCodes; i++) {
            oldfont->widths[i] =
                name2width(oldfont->t3font, ev->chars[i]);
            if (newfont->monospace && oldfont->widths[i])
                oldfont->widths[i] = newfont->monospace;
        }
        ev->flags |= PDC_ENC_USED;

        oldfont->name = fname;

        return oldslot;
    }

    p->fonts_number++;

    /* copy the complete font structure */
    memcpy(newfont, oldfont, sizeof(pdc_font));

    /* make copies of relevant strings to ensure correct cleanup */
    newfont->name = fname;
    newfont->apiname = pdc_strdup(p->pdc, fontname);

    /* modify relevant entries */
    newfont->used_on_current_page       = pdc_false;
    newfont->encoding                   = enc;
    newfont->obj_id                     = pdc_alloc_id(p->out);

    newfont->t3font = (pdc_t3font*)pdc_malloc(p->pdc, sizeof(pdc_t3font), fn);
    pdf_init_t3font_struct(p, newfont->t3font, oldfont->t3font->capacity);

    /* copy relevant entries of Type 3 structure */
    newfont->t3font->charprocs_id = oldfont->t3font->charprocs_id;
    newfont->t3font->res_id = oldfont->t3font->res_id;
    newfont->t3font->colorized = oldfont->t3font->colorized;
    memcpy(&newfont->t3font->matrix, &oldfont->t3font->matrix,
        sizeof(pdc_matrix));
    memcpy(&newfont->t3font->bbox, &oldfont->t3font->bbox,
        sizeof(pdc_rectangle));

    /* copy the glyph/width list from oldfont to newfont */
    newfont->t3font->next_glyph = oldfont->t3font->next_glyph;
    for (i = 0; i < newfont->t3font->next_glyph; ++i) {
        newfont->t3font->glyphs[i].width =
            oldfont->t3font->glyphs[i].width;
        newfont->t3font->glyphs[i].charproc_id =
            oldfont->t3font->glyphs[i].charproc_id;
        newfont->t3font->glyphs[i].name =
            pdc_strdup(p->pdc, oldfont->t3font->glyphs[i].name);
    }

    newfont->widths = (int *) pdc_calloc(p->pdc,
                                 newfont->numOfCodes * sizeof(int), fn);
    for (i = 0; i < newfont->numOfCodes; i++) {
        newfont->widths[i] =
            name2width(newfont->t3font, p->encodings[enc].ev->chars[i]);
        if (newfont->monospace && oldfont->widths[i])
            newfont->widths[i] = newfont->monospace;
    }
    p->encodings[enc].ev->flags |= PDC_ENC_USED;

    return slot;
}
Exemple #13
0
void
pdf__begin_glyph(
    PDF *p,
    const char *glyphname,
    float wx, float llx, float lly, float urx, float ury)
{
    static const char fn[] = "pdf__begin_glyph";
    pdc_t3font *t3font;
    pdc_t3glyph *glyph;
    int i;

    t3font = p->t3font;

    if (t3font->colorized == pdc_true &&
        (llx != (float) 0 || lly != (float) 0 ||
         urx != (float) 0 || ury != (float) 0))
        pdc_error(p->pdc, PDF_E_T3_BADBBOX, t3font->fontname, 0, 0, 0);

    PDF_SET_STATE(p, pdf_state_glyph);

    for (i = 0; i < t3font->next_glyph; ++i) {
        if (!strcmp(t3font->glyphs[i].name, glyphname)) {
            pdc_error(p->pdc, PDF_E_T3_GLYPH, glyphname,
                      t3font->fontname, 0, 0);
        }
    }

    if (t3font->next_glyph == t3font->capacity) {
        t3font->capacity *= 2;
        t3font->glyphs = (pdc_t3glyph *) pdc_realloc(p->pdc, t3font->glyphs,
            t3font->capacity * sizeof (pdc_t3glyph), fn);
    }

    glyph               = &t3font->glyphs[t3font->next_glyph];
    glyph->charproc_id  = pdc_begin_obj(p->out, PDC_NEW_ID);
    glyph->name         = pdc_strdup(p->pdc, glyphname);

    /* see comment in p_font.c for explanation */
    glyph->width        = 1000 * wx * t3font->matrix.a;

    /* if the strdup above fails, cleanup won't touch this slot. */
    ++t3font->next_glyph;

    p->contents = c_page;
                                                /* glyph description */
    pdc_begin_dict(p->out);                     /* glyph description dict */

    p->length_id = pdc_alloc_id(p->out);
    pdc_printf(p->out, "/Length %ld 0 R\n", p->length_id);

    if (pdc_get_compresslevel(p->out))
        pdc_puts(p->out, "/Filter/FlateDecode\n");

    pdc_end_dict(p->out);                       /* glyph description dict */

    pdc_begin_pdfstream(p->out);                /* glyph description stream */

    p->next_content++;

    if (t3font->colorized == pdc_true)
        pdc_printf(p->out, "%f 0 d0\n", wx);
    else {
        pdc_printf(p->out, "%f 0 %f %f %f %f d1\n", wx, llx, lly, urx, ury);

        /* adjust the font's bounding box */
        if (llx < t3font->bbox.llx)
            t3font->bbox.llx = llx;
        if (lly < t3font->bbox.lly)
            t3font->bbox.lly = lly;
        if (urx > t3font->bbox.urx)
            t3font->bbox.urx = urx;
        if (ury > t3font->bbox.ury)
            t3font->bbox.ury = ury;
    }
}
Exemple #14
0
void
pdf__begin_font(
    PDF *p,
    const char *fontname,
    float a, float b, float c, float d, float e, float f,
    const char *optlist)
{
    static const char fn[] = "pdf__begin_font";
    pdc_resopt *results;
    pdc_font *font;
    float det;
    int colorized = pdc_false;
    int slot;

    /* parsing optlist */
    results = pdc_parse_optionlist(p->pdc, optlist, pdf_begin_font_options,
                                   NULL, pdc_true);
    pdc_get_optvalues(p->pdc, "colorized", results, &colorized, NULL);
    pdc_cleanup_optionlist(p->pdc, results);

    det = a*d - b*c;

    if (det == 0)
        pdc_error(p->pdc, PDC_E_ILLARG_MATRIX,
            pdc_errprintf(p->pdc, "%f %f %f %f %f %f", a, b, c, d, e, f),
            0, 0, 0);

    /* look for an already existing font */
    for (slot = 0; slot < p->fonts_number; slot++)
    {
        if (!strcmp(p->fonts[slot].apiname, fontname))
        {
            pdc_error(p->pdc, PDF_E_T3_FONTEXISTS, fontname, 0, 0, 0);
        }
    }

    PDF_SET_STATE(p, pdf_state_font);

    pdf_init_tstate(p);
    pdf_init_gstate(p);
    pdf_init_cstate(p);

    /* slot for new font struct */
    slot = pdf_init_newfont(p);
    font = &p->fonts[slot];
    p->fonts_number++;

    /*
     * We store the new font in a font slot marked with "invalidenc" encoding.
     * When the font is used for the first time we modify the encoding.
     * Later uses will make a copy if the encoding is different.
     */

    font->type          = pdc_Type3;
    font->obj_id        = pdc_alloc_id(p->out);

    font->name          = NULL;
    font->apiname       = pdc_strdup(p->pdc, fontname);
    font->encoding      = pdc_invalidenc;  /* initially there is no encoding */
    font->widths        = (int *) pdc_calloc(p->pdc,
                                 font->numOfCodes * sizeof(int), fn);

    font->t3font = (pdc_t3font*) pdc_malloc(p->pdc, sizeof(pdc_t3font), fn);
    pdf_init_t3font_struct(p, font->t3font, T3GLYPHS_CHUNKSIZE);

    font->t3font->fontname      = pdc_strdup(p->pdc, fontname);
    font->t3font->colorized     = colorized;

    /* the resource id is needed until the font dict is written */
    font->t3font->res_id        = pdc_alloc_id(p->out);

    font->t3font->matrix.a      = a;
    font->t3font->matrix.b      = b;
    font->t3font->matrix.c      = c;
    font->t3font->matrix.d      = d;
    font->t3font->matrix.e      = e;
    font->t3font->matrix.f      = f;

    /* We won't receive glyph bounding box values for colorized true,
     * so we use the font matrix to get an approximation instead.
     *
     * Writing the font matrix should be optional according to the
     * PDF reference, but we must write it in order to work around a
     * display bug in Acrobat.
     */
    if (font->t3font->colorized == pdc_true) {
        font->t3font->bbox.llx = 0;
        font->t3font->bbox.lly = 0;
        font->t3font->bbox.urx = (d-b)/det;
        font->t3font->bbox.ury = (a-c)/det;
    }

    /*
     * We must store a pointer to the current font because its glyph
     * definitions may use other fonts and we would be unable to find
     * "our" current font again. This pointer lives throughout the
     * font definition, and will be reset in PDF_end_font() below.
     */
    p->t3font = font->t3font;
}
Exemple #15
0
PDFLIB_API int PDFLIB_CALL
PDF_create_gstate(PDF *p, const char *optlist)
{
    static const char fn[] = "PDF_create_gstate";
    pdf_extgstateresource *gs;
    int slot = -1;
    int font = pdc_undef;
    int inum;
    pdc_clientdata data;
    pdc_resopt *results;

    if (!pdf_enter_api(p, fn,
        (pdf_state) (pdf_state_document | pdf_state_content),
        "(p[%p], \"%s\")", (void *) p, optlist))
    {
        PDF_RETURN_HANDLE(p, slot)
    }

    if (optlist == NULL || !*optlist)
        pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "optlist", 0, 0, 0);

    slot = p->extgstates_number;
    if (slot == p->extgstates_capacity)
        pdf_grow_extgstates(p);

    p->extgstates_number++;
    gs = &p->extgstates[slot];
    gs->obj_id = pdc_alloc_id(p->out);

    /* parsing optlist */
    data.compatibility = p->compatibility;
    data.maxfont = p->fonts_number - 1;
    data.hastobepos = p->hastobepos;
    results = pdc_parse_optionlist(p->pdc, optlist, pdf_create_gstate_options,
                                   &data, pdc_true);

    pdc_get_optvalues(p->pdc, "alphaisshape", results,
                      &gs->alpha_is_shape, NULL);

    if (pdc_get_optvalues(p->pdc, "blendmode", results,
                      &inum, NULL))
        gs->blendmode = (pdf_blendmode) inum;

    gs->dash_count = pdc_get_optvalues(p->pdc, "dasharray", results,
                                       NULL, (void **) &gs->dash_array);

    pdc_get_optvalues(p->pdc, "dashphase", results,
                      &gs->dash_phase, NULL);

    pdc_get_optvalues(p->pdc, "flatness", results,
                      &gs->flatness, NULL);

    pdc_get_optvalues(p->pdc, "font", results, &font, NULL);
    if (font != pdc_undef)
        gs->font_obj = p->fonts[font].obj_id;

    pdc_get_optvalues(p->pdc, "fontsize", results,
                      &gs->font_size, NULL);

    pdc_get_optvalues(p->pdc, "linecap", results,
                      &gs->line_cap, NULL);

    pdc_get_optvalues(p->pdc, "linejoin", results,
                      &gs->line_join, NULL);

    pdc_get_optvalues(p->pdc, "linewidth", results,
                      &gs->line_width, NULL);

    pdc_get_optvalues(p->pdc, "miterlimit", results,
                      &gs->miter_limit, NULL);

    pdc_get_optvalues(p->pdc, "opacityfill", results,
                      &gs->opacity_fill, NULL);

    pdc_get_optvalues(p->pdc, "opacitystroke", results,
                      &gs->opacity_stroke, NULL);

    pdc_get_optvalues(p->pdc, "overprintfill", results,
                      &gs->overprint_fill, NULL);

    pdc_get_optvalues(p->pdc, "overprintmode", results,
                      &gs->overprint_mode, NULL);

    pdc_get_optvalues(p->pdc, "overprintstroke", results,
                      &gs->overprint_stroke, NULL);

    if (pdc_get_optvalues(p->pdc, "renderingintent", results,
                          &inum, NULL))
        gs->ri = (pdf_renderingintent) inum;

    pdc_get_optvalues(p->pdc, "smoothness", results,
                      &gs->smoothness, NULL);

    pdc_get_optvalues(p->pdc, "strokeadjust", results,
                      &gs->stroke_adjust, NULL);

    pdc_get_optvalues(p->pdc, "textknockout", results,
                      &gs->text_knockout, NULL);

    pdc_cleanup_optionlist(p->pdc, results);

    PDF_RETURN_HANDLE(p, slot)
}