summaryrefslogtreecommitdiff
path: root/source/fitz/writer.c
blob: f9d5b8c1a4b3c4daef5655ecb3005d1e65dcfb58 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
#include "mupdf/fitz.h"

/* Return non-null terminated pointers to key/value entries in comma separated
 * option string. A plain key has the default value 'yes'. Use strncmp to compare
 * key/value strings. */
static const char *
fz_get_option(fz_context *ctx, const char **key, const char **val, const char *opts)
{
	if (!opts || *opts == 0)
		return NULL;

	if (*opts == ',')
		++opts;

	*key = opts;
	while (*opts != 0 && *opts != ',' && *opts != '=')
		++opts;

	if (*opts == '=')
	{
		*val = ++opts;
		while (*opts != 0 && *opts != ',')
			++opts;
	}
	else
	{
		*val = "yes";
	}

	return opts;
}

int
fz_has_option(fz_context *ctx, const char *opts, const char *key, const char **val)
{
	const char *straw;
	size_t n = strlen(key);
	while ((opts = fz_get_option(ctx, &straw, val, opts)))
		if (!strncmp(straw, key, n) && (straw[n] == '=' || straw[n] == ',' || straw[n] == 0))
			return 1;
	return 0;
}

int
fz_option_eq(const char *a, const char *b)
{
	size_t n = strlen(b);
	return !strncmp(a, b, n) && (a[n] == ',' || a[n] == 0);
}

fz_document_writer *fz_new_document_writer_of_size(fz_context *ctx, size_t size, fz_document_writer_begin_page_fn *begin_page,
	fz_document_writer_end_page_fn *end_page, fz_document_writer_close_writer_fn *close, fz_document_writer_drop_writer_fn *drop)
{
	fz_document_writer *wri = Memento_label(fz_calloc(ctx, 1, size), "fz_document_writer");

	wri->begin_page = begin_page;
	wri->end_page = end_page;
	wri->close_writer = close;
	wri->drop_writer = drop;

	return wri;
}

fz_document_writer *
fz_new_document_writer(fz_context *ctx, const char *path, const char *format, const char *options)
{
	if (!format)
	{
		format = strrchr(path, '.');
		if (!format)
			fz_throw(ctx, FZ_ERROR_GENERIC, "cannot detect document format");
		format += 1; /* skip the '.' */
	}

	if (!fz_strcasecmp(format, "cbz"))
		return fz_new_cbz_writer(ctx, path, options);
#if FZ_ENABLE_PDF
	if (!fz_strcasecmp(format, "pdf"))
		return fz_new_pdf_writer(ctx, path, options);
#endif
	if (!fz_strcasecmp(format, "svg"))
		return fz_new_svg_writer(ctx, path, options);

	if (!fz_strcasecmp(format, "png"))
		return fz_new_pixmap_writer(ctx, path, options, "out-%04.png", 0, fz_save_pixmap_as_png);
	if (!fz_strcasecmp(format, "tga"))
		return fz_new_pixmap_writer(ctx, path, options, "out-%04.tga", 0, fz_save_pixmap_as_tga);
	if (!fz_strcasecmp(format, "pam"))
		return fz_new_pixmap_writer(ctx, path, options, "out-%04.pam", 0, fz_save_pixmap_as_pam);
	if (!fz_strcasecmp(format, "pnm"))
		return fz_new_pixmap_writer(ctx, path, options, "out-%04.pnm", 0, fz_save_pixmap_as_pnm);
	if (!fz_strcasecmp(format, "pgm"))
		return fz_new_pixmap_writer(ctx, path, options, "out-%04.pgm", 1, fz_save_pixmap_as_pnm);
	if (!fz_strcasecmp(format, "ppm"))
		return fz_new_pixmap_writer(ctx, path, options, "out-%04.ppm", 3, fz_save_pixmap_as_pnm);
	if (!fz_strcasecmp(format, "pbm"))
		return fz_new_pixmap_writer(ctx, path, options, "out-%04.pbm", 1, fz_save_pixmap_as_pbm);
	if (!fz_strcasecmp(format, "pkm"))
		return fz_new_pixmap_writer(ctx, path, options, "out-%04.pkm", 4, fz_save_pixmap_as_pkm);

	fz_throw(ctx, FZ_ERROR_GENERIC, "unknown output document format: %s", format);
}

void
fz_close_document_writer(fz_context *ctx, fz_document_writer *wri)
{
	if (wri->close_writer)
		wri->close_writer(ctx, wri);
	wri->close_writer = NULL;
}

void
fz_drop_document_writer(fz_context *ctx, fz_document_writer *wri)
{
	if (!wri)
		return;

	if (wri->close_writer)
		fz_warn(ctx, "dropping unclosed document writer");
	if (wri->drop_writer)
		wri->drop_writer(ctx, wri);
	fz_free(ctx, wri);
}

fz_device *
fz_begin_page(fz_context *ctx, fz_document_writer *wri, const fz_rect *mediabox)
{
	return wri->begin_page(ctx, wri, mediabox);
}

void
fz_end_page(fz_context *ctx, fz_document_writer *wri, fz_device *dev)
{
	wri->end_page(ctx, wri, dev);
}