Пример #1
0
PDFLIB_API void PDFLIB_CALL
PDF_skew(PDF *p, float alpha, float beta)
{
    static const char fn[] = "PDF_skew";
    pdc_matrix m;

    if (!pdf_enter_api(p, fn, pdf_state_content, "(p[%p], %g, %g)\n",
	(void *) p, alpha, beta))
	return;

    if (alpha == (float) 0 && beta == (float) 0)
	return;

    if (alpha > (float) 360 || alpha < (float) -360 ||
	alpha == (float) -90 || alpha == (float) -270 ||
	alpha == (float) 90 || alpha == (float) 270) {
	pdc_error(p->pdc, PDC_E_ILLARG_FLOAT,
	    "alpha", pdc_errprintf(p->pdc, "%f", alpha), 0, 0);
    }

    if (beta > (float) 360 || beta < (float) -360 ||
	beta == (float) -90 || beta == (float) -270 ||
	beta == (float) 90 || beta == (float) 270) {
	pdc_error(p->pdc, PDC_E_ILLARG_FLOAT,
	    "beta", pdc_errprintf(p->pdc, "%f", beta), 0, 0);
    }

    pdc_skew_matrix(p->ydirection * alpha, p->ydirection * beta, &m);

    pdf_concat_raw(p, &m);
}
Пример #2
0
void
pdf__skew(PDF *p, pdc_scalar alpha, pdc_scalar beta)
{
    pdc_matrix m;

    pdc_check_number(p->pdc, "alpha", alpha);
    pdc_check_number(p->pdc, "beta", beta);

    if (alpha == 0 && beta == 0)
	return;

    if (alpha > 360 || alpha < -360 ||
	alpha == -90 || alpha == -270 ||
	alpha == 90 || alpha == 270)
    {
	pdc_error(p->pdc, PDC_E_ILLARG_FLOAT,
	    "alpha", pdc_errprintf(p->pdc, "%f", alpha), 0, 0);
    }

    if (beta > 360 || beta < -360 ||
	beta == -90 || beta == -270 ||
	beta == 90 || beta == 270)
    {
	pdc_error(p->pdc, PDC_E_ILLARG_FLOAT,
	    "beta", pdc_errprintf(p->pdc, "%f", beta), 0, 0);
    }

    pdc_skew_matrix(p->ydirection * alpha, p->ydirection * beta, &m);

    pdf_concat_raw(p, &m);
}
Пример #3
0
PDFLIB_API void PDFLIB_CALL
PDF_setpolydash(PDF *p, float *darray, int length)
{
    static const char fn[] = "PDF_setpolydash";

    int i;

    for (i = 0; i < length; i++)
	pdc_trace(p->pdc, "*(darray+%d) = %g;\n", i, darray[i]);

    if (!pdf_enter_api(p, fn, pdf_state_content,
	"(p[%p], darray[%p], %d)\n", (void *) p, (void *) darray, length))
    {
	return;
    }

    if (length > 1)
    {
        /* sanity checks */
        if (!darray)
            pdc_error(p->pdc, PDC_E_ILLARG_EMPTY, "darray", 0, 0, 0);

        if (length < 0 || length > MAX_DASH_LENGTH)
            pdc_error(p->pdc, PDC_E_ILLARG_INT,
                "length", pdc_errprintf(p->pdc, "%d", length), 0, 0);

        for (i = 0; i < length; i++) {
            if (darray[i] < (float) 0.0)
                pdc_error(p->pdc, PDC_E_ILLARG_FLOAT,
                    "darray[i]", pdc_errprintf(p->pdc, "%f", darray[i]), 0, 0);
        }
    }

    pdf__setdashpattern(p, darray, length, (float) 0.0);
}
Пример #4
0
static void
pdf_prepare_name_string(PDF *p, const char *name, int len, int maxlen,
                        char **newname, int *newlen,
                        pdc_encoding *htenc, int *htcp)
{
    if (name == NULL)
    {
        len = 0;
        name = "";
    }

    if (len < 0 || len > maxlen)
    {
        pdc_error(p->pdc, PDC_E_ILLARG_STRINGLEN,
                  pdc_errprintf(p->pdc, "%d", len),
                  pdc_errprintf(p->pdc, "%d", PDC_SHRT_MAX), 0, 0);
    }

    *newname = (char *) name;
    *newlen = len;
    *htenc = pdc_invalidenc;
    *htcp = 0;

    if (p->usehyptxtenc && !len && !pdc_is_utf8_bytecode(name))
    {
        *htenc = pdf_get_hypertextencoding_param(p, htcp);

    }
}
Пример #5
0
static float
pdf_pos_value(PDF *p, const char *key, float value, int minver)
{
    if (p->compatibility < minver)
	pdc_error(p->pdc, PDC_E_PAR_VERSION,
	    key, pdc_errprintf(p->pdc, "%d.%d", minver/10, minver%10), 0, 0);

    if (value <= (float) 0)
	pdc_error(p->pdc, PDC_E_PAR_ILLVALUE,
	    pdc_errprintf(p->pdc, "%f", value), key, 0, 0);

    return value;
}
Пример #6
0
void
pdf_check_handle(PDF *p, int handle, pdc_opttype type)
{
    if (pdf_check_opt_handle(p, handle, type))
    {
        if (p->pdc->hastobepos && type != pdc_stringhandle)
            handle++;

        pdc_error(p->pdc, PDC_E_ILLARG_HANDLE,
                  pdc_errprintf(p->pdc, "%.*s", PDC_ERR_MAXSTRLEN,
                                pdc_get_handletype(type)),
                  pdc_errprintf(p->pdc, "%d", handle), 0, 0);
    }
}
Пример #7
0
/* set a new maximum for the number of simultaneously open files.
 * if return = -1 error occured
 */
int
pdc_set_maxfilehandles(pdc_core *pdc, int maxfps)
{
    const char *stemp = pdc_errprintf(pdc, "%d", maxfps);

    if (maxfps < _IOB_ENTRIES)
        pdc_error(pdc, PDC_E_IO_TOOFEW_REQFILEHDLS, stemp,
                  pdc_errprintf(pdc, "%d", _IOB_ENTRIES), 0, 0);

    if (maxfps > PDC_MAXFILEHANDLES)
        pdc_error(pdc, PDC_E_IO_TOOMANY_REQFILEHDLS, stemp,
                  pdc_errprintf(pdc, "%d", PDC_MAXFILEHANDLES), 0, 0);

    return _setmaxstdio(maxfps);
}
Пример #8
0
int
pdc_get_keymask_ci(pdc_core *pdc, const char *option,
                   const char *keywordlist, const pdc_keyconn *keyconn)
{
    char **keys = NULL;
    int nkeys, i, j, k = 0;

    nkeys = pdc_split_stringlist(pdc, keywordlist, NULL, 0, &keys);

    for (j = 0; j < nkeys; j++)
    {
        for (i = 0; keyconn[i].word != NULL; i++)
            if (!pdc_stricmp(keys[j], keyconn[i].word))
                break;

        if (keyconn[i].word == NULL)
        {
            const char *stemp = pdc_errprintf(pdc, "%.*s",
                                              PDC_ERR_MAXSTRLEN, keys[j]);
            pdc_cleanup_stringlist(pdc, keys);
            pdc_set_errmsg(pdc, PDC_E_OPT_ILLKEYWORD, option, stemp, 0, 0);
            return PDC_KEY_NOTFOUND;
        }

        k |= keyconn[i].code;
    }

    pdc_cleanup_stringlist(pdc, keys);
    return k;
}
Пример #9
0
/*
 * pdc_convert_filename_ext converts a file name as string of name type
 * (see function pdc_convert_name) to a [EBCDIC-]UTF-8 string with or
 * without a BOM. If the compiler doesn't allow Unicode filenames
 * (see define PDC_UNICODE_FILENAME) the filename is Latin-1 encoded
 * if possible or an exception will be thrown.
 *
 */
const char *
pdc_convert_filename_ext(pdc_core *pdc, const char *filename, int len,
                         const char *paramname, pdc_encoding enc, int codepage,
                         int flags)
{
    char *fname = NULL;
    const char *outfilename = NULL;
    int i = 0;

    if (filename == NULL)
        pdc_error(pdc, PDC_E_ILLARG_EMPTY, paramname, 0, 0, 0);

    fname = pdc_convert_name_ext(pdc, filename, len, enc, codepage, flags);

    if (fname == NULL || *fname == '\0')
        pdc_error(pdc, PDC_E_ILLARG_EMPTY, paramname, 0, 0, 0);

    if (pdc_is_utf8_bytecode(fname))
    {
#if defined(PDC_UNICODE_FILENAME)
        i = 3;
#else
        fname = pdc_check_filename(pdc, fname);
#endif
    }

    outfilename = pdc_errprintf(pdc, "%s", &fname[i]);
    pdc_free(pdc, fname);

    return outfilename;
}
Пример #10
0
void
pdc_set_fopen_errmsg(pdc_core *pdc, int errnum, const char *qualifier,
                     const char *filename)
{
    const char *stemp1 = NULL;
    const char *stemp2 = NULL;
    int errno1 = errno;

#if defined(EMACOSERR) && defined(MAC)
    errno1 = (int) __MacOSErrNo;
#endif

    errnum = pdc_get_fopen_errnum(pdc, errnum);
    if (errnum == PDC_E_IO_RDOPEN)
        errnum = PDC_E_IO_RDOPEN_CODE;
    else if (errnum == PDC_E_IO_WROPEN)
        errnum = PDC_E_IO_WROPEN_CODE;
    if (errnum == PDC_E_IO_RDOPEN_CODE || errnum == PDC_E_IO_WROPEN_CODE)
    {
        stemp1 = pdc_errprintf(pdc, "%d", errno1);

#ifdef PDC_HAS_STRERROR
        stemp2 = strerror(errno1);
        if (stemp2 != NULL)
        {
            if (errnum == PDC_E_IO_RDOPEN_CODE)
                errnum = PDC_E_IO_RDOPEN_CODETEXT;
            else if (errnum == PDC_E_IO_WROPEN_CODE)
                errnum = PDC_E_IO_WROPEN_CODETEXT;
        }
#endif
    }

    pdc_set_errmsg(pdc, errnum, qualifier, filename, stemp1, stemp2);
}
Пример #11
0
static pdc_bool
pdf_colorspace_equal(PDF *p, pdf_colorspace *cs1, pdf_colorspace *cs2)
{
    static const char *fn = "pdf_colorspace_equal";

    if (cs1->type != cs2->type)
	return pdc_false;

    switch (cs1->type) {
	case DeviceGray:
	case DeviceRGB:
	case DeviceCMYK:
	return pdc_true;
	break;


	case Indexed:
	return ((cs1->val.indexed.base == cs2->val.indexed.base) &&
		(cs1->val.indexed.palette_size==cs2->val.indexed.palette_size)&&
		(cs1->val.indexed.colormap_id != PDC_BAD_ID &&
		 cs1->val.indexed.colormap_id == cs2->val.indexed.colormap_id));
	break;

	case PatternCS:
	return (cs1->val.pattern.base == cs2->val.pattern.base);
	break;


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

    return pdc_false;
} /* pdf_colorspace_equal */
Пример #12
0
void
pdf_concat_raw(PDF *p, pdc_matrix *m)
{
    if (!pdc_is_identity_matrix(m))
    {
        char sa[32], sb[32], sc[32], sd[32];

        pdc_sprintf(p->pdc, pdc_true, sa, "%f", m->a);
        pdc_sprintf(p->pdc, pdc_true, sb, "%f", m->b);
        pdc_sprintf(p->pdc, pdc_true, sc, "%f", m->c);
        pdc_sprintf(p->pdc, pdc_true, sd, "%f", m->d);

        if ((!strcmp(sa, "0") || !strcmp(sd, "0")) &&
            (!strcmp(sb, "0") || !strcmp(sc, "0")))
        {
            pdc_error(p->pdc, PDC_E_ILLARG_MATRIX,
                      pdc_errprintf(p->pdc, "%f %f %f %f %f %f",
                                    m->a, m->b, m->c, m->d, m->e, m->f),
                      0, 0, 0);
        }

        pdf_end_text(p);

        pdc_printf(p->out, "%s %s %s %s %f %f cm\n",
                   sa, sb, sc, sd, m->e, m->f);

        pdc_multiply_matrix(m, &p->curr_ppt->gstate[p->curr_ppt->sl].ctm);
    }
}
Пример #13
0
PDFLIB_API void PDFLIB_CALL
PDF_setmatrix(PDF *p, float a, float b, float c, float d, float e, float f)
{
    static const char fn[] = "PDF_setmatrix";
    pdc_matrix m;
    float det = a * d - b * c;

    if (!pdf_enter_api(p, fn, pdf_state_content,
	"(p[%p], %g, %g, %g, %g, %g, %g)\n", (void *) p, a, b, c, d, e, f))
    {
	return;
    }

    if (fabs(det) < (float) PDF_SMALLREAL)
	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);

    pdc_invert_matrix(p->pdc, &m, &p->gstate[p->sl].ctm);
    pdf_concat_raw(p, &m);

    m.a = (float) a;
    m.b = (float) b;
    m.c = (float) c;
    m.d = (float) d;
    m.e = (float) e;
    m.f = (float) f;

    pdf_concat_raw(p, &m);
}
Пример #14
0
PDFLIB_API void PDFLIB_CALL
PDF_setdash(PDF *p, float b, float w)
{
    static const char fn[] = "PDF_setdash";

    if (!pdf_enter_api(p, fn, pdf_state_content, "(p[%p], %g, %g)\n",
	(void *) p, b, w))
	return;

    if (b < (float) 0.0)
	pdc_error(p->pdc, PDC_E_ILLARG_FLOAT,
	    "b", pdc_errprintf(p->pdc, "%f", b), 0, 0);

    if (w < (float) 0.0)
	pdc_error(p->pdc, PDC_E_ILLARG_FLOAT,
	    "w", pdc_errprintf(p->pdc, "%f", w), 0, 0);

    pdf__setdash(p, b, w);
}
Пример #15
0
const char *
pdf_current_scope(PDF *p)
{
    const char *scopename =
        pdc_get_keyword(PDF_GET_STATE(p), pdf_scope_keylist);

    if (!scopename)
        pdc_error(p->pdc, PDF_E_INT_BADSCOPE,
            pdc_errprintf(p->pdc, " (0x%08X)", PDF_GET_STATE(p)), 0, 0, 0);

    return (char *) scopename;	/* be happy, compiler! */
}
Пример #16
0
pdc_ucval
pdc_us_get(const pdc_ustr *s, int idx)
{
    static const char fn[] = "pdc_us_get";

    const pdc_ucval *buf = s->buf ? s->buf : s->buf0;

    if (idx < 0 || s->len <= (size_t) idx)
	pdc_error(s->pdc, PDC_E_INT_ARRIDX,
	    pdc_errprintf(s->pdc, "%d", idx), fn, 0, 0);

    return buf[idx];
} /* pdc_us_get */
Пример #17
0
void
pdc_us_set(pdc_ustr *s, int idx, pdc_ucval val)
{
    static const char fn[] = "pdc_us_set";

    pdc_ucval *buf = s->buf ? s->buf : s->buf0;

    if (idx < 0 || s->len <= (size_t) idx)
	pdc_error(s->pdc, PDC_E_INT_ARRIDX,
	    pdc_errprintf(s->pdc, "%d", idx), fn, 0, 0);

    buf[idx] = val;
} /* pdc_us_set */
Пример #18
0
static double
pdf_pos_value(PDF *p, const char *key, double value, int minver)
{
    if (p->compatibility < minver)
	pdc_error(p->pdc, PDC_E_PAR_VERSION,
            key, pdc_get_pdfversion(p->pdc, minver), 0, 0);

    if (value <= 0)
	pdc_error(p->pdc, PDC_E_PAR_ILLVALUE,
	    pdc_errprintf(p->pdc, "%f", value), key, 0, 0);

    return value;
}
Пример #19
0
static int
pdf_color_components(PDF *p, int slot)
{
    static const char *fn = "pdf_color_components";
    pdf_colorspace *cs;
    int components = 0;

    cs = &p->colorspaces[slot];

    switch (cs->type) {
	case DeviceGray:
	case Indexed:
	components = 1;
	break;

	case DeviceRGB:
	components = 3;
	break;

	case DeviceCMYK:
	components = 4;
	break;

	case PatternCS:
	if (cs->val.pattern.base == pdc_undef)
	    components = 0;	/* PaintType 1: colored pattern */
	else
	    components = pdf_color_components(p, cs->val.pattern.base);

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

    return components;
} /* pdf_color_components */
Пример #20
0
PDFLIB_API void PDFLIB_CALL
PDF_setmiterlimit(PDF *p, float miter)
{
    static const char fn[] = "PDF_setmiterlimit";

    if (!pdf_enter_api(p, fn, pdf_state_content, "(p[%p], %g)\n",
	(void *) p, miter))
	return;

    if (miter < (float) 1.0)
	pdc_error(p->pdc, PDC_E_ILLARG_FLOAT,
	    "miter", pdc_errprintf(p->pdc, "%f", miter), 0, 0);

    pdf__setmiterlimit(p, miter);
}
Пример #21
0
PDFLIB_API void PDFLIB_CALL
PDF_setflat(PDF *p, float flat)
{
    static const char fn[] = "PDF_setflat";

    if (!pdf_enter_api(p, fn, pdf_state_content, "(p[%p], %g)\n",
	(void *) p, flat))
	return;

    if (flat < 0.0 || flat > 100.0)
	pdc_error(p->pdc, PDC_E_ILLARG_FLOAT,
	    "flat", pdc_errprintf(p->pdc, "%f", flat), 0, 0);

    pdf__setflat(p, flat);
}
Пример #22
0
void
pdf_cleanup_colorspaces(PDF *p)
{
    static const char *fn = "pdf_cleanup_colorspaces";

    int i;

    if (!p->colorspaces)
	return;

    for (i = 0; i < p->colorspaces_number; i++) {
	pdf_colorspace *cs = &p->colorspaces[i];;

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

	    case Indexed:
	    if (cs->val.indexed.colormap)
		pdc_free(p->pdc, cs->val.indexed.colormap);
	    break;


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

    pdc_free(p->pdc, p->colorspaces);
    p->colorspaces = NULL;
}
Пример #23
0
PDFLIB_API void PDFLIB_CALL
PDF_setlinewidth(PDF *p, float width)
{
    static const char fn[] = "PDF_setlinewidth";

    if (!pdf_enter_api(p, fn, pdf_state_content, "(p[%p], %g)\n",
	(void *) p, width))
	return;

    if (width <= (float) 0.0)
	pdc_error(p->pdc, PDC_E_ILLARG_FLOAT,
	    "width", pdc_errprintf(p->pdc, "%f", width), 0, 0);

    pdf__setlinewidth(p, width);
}
Пример #24
0
PDFLIB_API void PDFLIB_CALL
PDF_setlinecap(PDF *p, int cap)
{
    static const char fn[] = "PDF_setlinecap";
    const int LAST_CAP = 2;

    if (!pdf_enter_api(p, fn, pdf_state_content, "(p[%p], %d)\n",
	(void *) p, cap))
	return;

    if (cap < 0 || cap > LAST_CAP)
	pdc_error(p->pdc, PDC_E_ILLARG_INT,
	    "cap", pdc_errprintf(p->pdc, "%d", cap), 0, 0);

    pdf__setlinecap(p, cap);
}
Пример #25
0
PDFLIB_API void PDFLIB_CALL
PDF_setlinejoin(PDF *p, int join)
{
    static const char fn[] = "PDF_setlinejoin";
    const int LAST_JOIN = 2;

    if (!pdf_enter_api(p, fn, pdf_state_content, "(p[%p], %d)\n",
	(void *) p, join))
	return;

    if (join < 0 || join > LAST_JOIN)
	pdc_error(p->pdc, PDC_E_ILLARG_INT,
	    "join", pdc_errprintf(p->pdc, "%d", join), 0, 0);

    pdf__setlinejoin(p, join);
}
Пример #26
0
void
pdf__setmatrix(PDF *p, pdc_matrix *n)
{
    pdc_matrix m;
    float det = n->a * n->d - n->b * n->c;

    if (fabs(det) < (float) PDF_SMALLREAL)
	pdc_error(p->pdc, PDC_E_ILLARG_MATRIX,
	    pdc_errprintf(p->pdc, "%f %f %f %f %f %f",
		n->a, n->b, n->c, n->d, n->e, n->f),
	    0, 0, 0);

    pdc_invert_matrix(p->pdc, &m, &p->gstate[p->sl].ctm);
    pdf_concat_raw(p, &m);
    pdf_concat_raw(p, n);
}
Пример #27
0
void
pdf__setlinecap(PDF *p, int cap)
{
    pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl];
    const int LAST_CAP = 2;

    if (cap < 0 || cap > LAST_CAP)
	pdc_error(p->pdc, PDC_E_ILLARG_INT,
	    "cap", pdc_errprintf(p->pdc, "%d", cap), 0, 0);

    if (cap != gs->lcap || PDF_FORCE_OUTPUT())
    {
        gs->lcap = cap;
        pdc_printf(p->out, "%d J\n", cap);
    }
}
Пример #28
0
void
pdf__setlinejoin(PDF *p, int join)
{
    pdf_gstate *gs = &p->curr_ppt->gstate[p->curr_ppt->sl];
    const int LAST_JOIN = 2;

    if (join < 0 || join > LAST_JOIN)
	pdc_error(p->pdc, PDC_E_ILLARG_INT,
	    "join", pdc_errprintf(p->pdc, "%d", join), 0, 0);

    if (join != gs->ljoin || PDF_FORCE_OUTPUT())
    {
        gs->ljoin = join;
        pdc_printf(p->out, "%d j\n", join);
    }
}
Пример #29
0
void
pdf_write_function_dict(PDF *p, pdf_color *c0, pdf_color *c1, pdc_scalar N)
{
    static const char *fn = "pdf_write_function_dict";

    pdf_colorspace *cs;

    cs = &p->colorspaces[c1->cs];

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

    pdc_puts(p->out, "/FunctionType 2\n");
    pdc_puts(p->out, "/Domain[0 1]\n");
    pdc_printf(p->out, "/N %f\n", N);

    switch (cs->type) {

	case DeviceGray:
	pdc_puts(p->out, "/Range[0 1]\n");
	if (c0->val.gray != 0) pdc_printf(p->out, "/C0[%f]\n", c0->val.gray);
	if (c1->val.gray != 1) pdc_printf(p->out, "/C1[%f]", c1->val.gray);
	break;

	case DeviceRGB:
	pdc_puts(p->out, "/Range[0 1 0 1 0 1]\n");
	pdc_printf(p->out, "/C0[%f %f %f]\n",
		c0->val.rgb.r, c0->val.rgb.g, c0->val.rgb.b);
	pdc_printf(p->out, "/C1[%f %f %f]",
		c1->val.rgb.r, c1->val.rgb.g, c1->val.rgb.b);
	break;

	case DeviceCMYK:
	pdc_puts(p->out, "/Range[0 1 0 1 0 1 0 1]\n");
	pdc_printf(p->out, "/C0[%f %f %f %f]\n",
		c0->val.cmyk.c, c0->val.cmyk.m, c0->val.cmyk.y, c0->val.cmyk.k);
	pdc_printf(p->out, "/C1[%f %f %f %f]",
		c1->val.cmyk.c, c1->val.cmyk.m, c1->val.cmyk.y, c1->val.cmyk.k);
	break;


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

    pdc_end_dict_c(p->out);		/* function dict */
} /* pdf_write_function_dict */
Пример #30
0
void
pdf__save(PDF *p)
{
    if (p->sl == PDF_MAX_SAVE_LEVEL - 1)
	pdc_error(p->pdc, PDF_E_GSTATE_SAVELEVEL,
	    pdc_errprintf(p->pdc, "%d", PDF_MAX_SAVE_LEVEL - 1), 0, 0, 0);

    pdf_end_text(p);

    pdc_puts(p->out, "q\n");

    /* propagate states to next level */
    p->sl++;
    memcpy(&p->gstate[p->sl], &p->gstate[p->sl - 1], sizeof(pdf_gstate));
    memcpy(&p->tstate[p->sl], &p->tstate[p->sl - 1], sizeof(pdf_tstate));
    memcpy(&p->cstate[p->sl], &p->cstate[p->sl - 1], sizeof(pdf_cstate));
}