summaryrefslogtreecommitdiff
path: root/fitz
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2013-02-04 17:06:50 +0000
committerRobin Watts <robin.watts@artifex.com>2013-02-04 23:18:18 +0000
commitd13793b9e3511b0a1ada04c1863527e2bc948f1a (patch)
treeaf9e79f45fea8043cb165f33a4cc0e9fbe508254 /fitz
parentfc9281079e0b15a219337fe6e1ad8f8d1389bad1 (diff)
downloadmupdf-d13793b9e3511b0a1ada04c1863527e2bc948f1a.tar.xz
Add fz_output, and make output functions use it.
Various functions in the code output to FILE *, when there are times we'd like them to output to other things, such as fz_buffers. Add an fz_output type, together with fz_printf to allow things to output to this.
Diffstat (limited to 'fitz')
-rw-r--r--fitz/dev_text.c96
-rw-r--r--fitz/doc_outline.c20
-rw-r--r--fitz/fitz-internal.h8
-rw-r--r--fitz/fitz.h37
-rw-r--r--fitz/stm_buffer.c34
-rw-r--r--fitz/stm_output.c65
6 files changed, 187 insertions, 73 deletions
diff --git a/fitz/dev_text.c b/fitz/dev_text.c
index a5d765eb..e5b2c927 100644
--- a/fitz/dev_text.c
+++ b/fitz/dev_text.c
@@ -569,43 +569,43 @@ static int font_is_italic(fz_font *font)
}
static void
-fz_print_style_begin(FILE *out, fz_text_style *style)
+fz_print_style_begin(fz_output *out, fz_text_style *style)
{
int script = style->script;
- fprintf(out, "<span class=\"s%d\">", style->id);
+ fz_printf(out, "<span class=\"s%d\">", style->id);
while (script-- > 0)
- fprintf(out, "<sup>");
+ fz_printf(out, "<sup>");
while (++script < 0)
- fprintf(out, "<sub>");
+ fz_printf(out, "<sub>");
}
static void
-fz_print_style_end(FILE *out, fz_text_style *style)
+fz_print_style_end(fz_output *out, fz_text_style *style)
{
int script = style->script;
while (script-- > 0)
- fprintf(out, "</sup>");
+ fz_printf(out, "</sup>");
while (++script < 0)
- fprintf(out, "</sub>");
- fprintf(out, "</span>");
+ fz_printf(out, "</sub>");
+ fz_printf(out, "</span>");
}
static void
-fz_print_style(FILE *out, fz_text_style *style)
+fz_print_style(fz_output *out, fz_text_style *style)
{
char *s = strchr(style->font->name, '+');
s = s ? s + 1 : style->font->name;
- fprintf(out, "span.s%d{font-family:\"%s\";font-size:%gpt;",
+ fz_printf(out, "span.s%d{font-family:\"%s\";font-size:%gpt;",
style->id, s, style->size);
if (font_is_italic(style->font))
- fprintf(out, "font-style:italic;");
+ fz_printf(out, "font-style:italic;");
if (font_is_bold(style->font))
- fprintf(out, "font-weight:bold;");
- fprintf(out, "}\n");
+ fz_printf(out, "font-weight:bold;");
+ fz_printf(out, "}\n");
}
void
-fz_print_text_sheet(fz_context *ctx, FILE *out, fz_text_sheet *sheet)
+fz_print_text_sheet(fz_context *ctx, fz_output *out, fz_text_sheet *sheet)
{
fz_text_style *style;
for (style = sheet->style; style; style = style->next)
@@ -613,7 +613,7 @@ fz_print_text_sheet(fz_context *ctx, FILE *out, fz_text_sheet *sheet)
}
void
-fz_print_text_page_html(fz_context *ctx, FILE *out, fz_text_page *page)
+fz_print_text_page_html(fz_context *ctx, fz_output *out, fz_text_page *page)
{
int block_n, line_n, span_n, ch_n;
fz_text_style *style = NULL;
@@ -621,16 +621,16 @@ fz_print_text_page_html(fz_context *ctx, FILE *out, fz_text_page *page)
fz_text_line *line;
fz_text_span *span;
- fprintf(out, "<div class=\"page\">\n");
+ fz_printf(out, "<div class=\"page\">\n");
for (block_n = 0; block_n < page->len; block_n++)
{
block = &page->blocks[block_n];
- fprintf(out, "<div class=\"block\">\n");
+ fz_printf(out, "<div class=\"block\">\n");
for (line_n = 0; line_n < block->len; line_n++)
{
line = &block->lines[line_n];
- fprintf(out, "<p>");
+ fz_printf(out, "<p>");
style = NULL;
for (span_n = 0; span_n < line->len; span_n++)
@@ -648,29 +648,29 @@ fz_print_text_page_html(fz_context *ctx, FILE *out, fz_text_page *page)
{
fz_text_char *ch = &span->text[ch_n];
if (ch->c == '<')
- fprintf(out, "&lt;");
+ fz_printf(out, "&lt;");
else if (ch->c == '>')
- fprintf(out, "&gt;");
+ fz_printf(out, "&gt;");
else if (ch->c == '&')
- fprintf(out, "&amp;");
+ fz_printf(out, "&amp;");
else if (ch->c >= 32 && ch->c <= 127)
- fprintf(out, "%c", ch->c);
+ fz_printf(out, "%c", ch->c);
else
- fprintf(out, "&#x%x;", ch->c);
+ fz_printf(out, "&#x%x;", ch->c);
}
}
if (style)
fz_print_style_end(out, style);
- fprintf(out, "</p>\n");
+ fz_printf(out, "</p>\n");
}
- fprintf(out, "</div>\n");
+ fz_printf(out, "</div>\n");
}
- fprintf(out, "</div>\n");
+ fz_printf(out, "</div>\n");
}
void
-fz_print_text_page_xml(fz_context *ctx, FILE *out, fz_text_page *page)
+fz_print_text_page_xml(fz_context *ctx, fz_output *out, fz_text_page *page)
{
fz_text_block *block;
fz_text_line *line;
@@ -678,54 +678,54 @@ fz_print_text_page_xml(fz_context *ctx, FILE *out, fz_text_page *page)
fz_text_char *ch;
char *s;
- fprintf(out, "<page>\n");
+ fz_printf(out, "<page>\n");
for (block = page->blocks; block < page->blocks + page->len; block++)
{
- fprintf(out, "<block bbox=\"%g %g %g %g\">\n",
+ fz_printf(out, "<block bbox=\"%g %g %g %g\">\n",
block->bbox.x0, block->bbox.y0, block->bbox.x1, block->bbox.y1);
for (line = block->lines; line < block->lines + block->len; line++)
{
- fprintf(out, "<line bbox=\"%g %g %g %g\">\n",
+ fz_printf(out, "<line bbox=\"%g %g %g %g\">\n",
line->bbox.x0, line->bbox.y0, line->bbox.x1, line->bbox.y1);
for (span = line->spans; span < line->spans + line->len; span++)
{
fz_text_style *style = span->style;
s = strchr(style->font->name, '+');
s = s ? s + 1 : style->font->name;
- fprintf(out, "<span bbox=\"%g %g %g %g\" font=\"%s\" size=\"%g\">\n",
+ fz_printf(out, "<span bbox=\"%g %g %g %g\" font=\"%s\" size=\"%g\">\n",
span->bbox.x0, span->bbox.y0, span->bbox.x1, span->bbox.y1,
s, style->size);
for (ch = span->text; ch < span->text + span->len; ch++)
{
- fprintf(out, "<char bbox=\"%g %g %g %g\" c=\"",
+ fz_printf(out, "<char bbox=\"%g %g %g %g\" c=\"",
ch->bbox.x0, ch->bbox.y0, ch->bbox.x1, ch->bbox.y1);
switch (ch->c)
{
- case '<': fprintf(out, "&lt;"); break;
- case '>': fprintf(out, "&gt;"); break;
- case '&': fprintf(out, "&amp;"); break;
- case '"': fprintf(out, "&quot;"); break;
- case '\'': fprintf(out, "&apos;"); break;
+ case '<': fz_printf(out, "&lt;"); break;
+ case '>': fz_printf(out, "&gt;"); break;
+ case '&': fz_printf(out, "&amp;"); break;
+ case '"': fz_printf(out, "&quot;"); break;
+ case '\'': fz_printf(out, "&apos;"); break;
default:
if (ch->c >= 32 && ch->c <= 127)
- fprintf(out, "%c", ch->c);
+ fz_printf(out, "%c", ch->c);
else
- fprintf(out, "&#x%x;", ch->c);
+ fz_printf(out, "&#x%x;", ch->c);
break;
}
- fprintf(out, "\"/>\n");
+ fz_printf(out, "\"/>\n");
}
- fprintf(out, "</span>\n");
+ fz_printf(out, "</span>\n");
}
- fprintf(out, "</line>\n");
+ fz_printf(out, "</line>\n");
}
- fprintf(out, "</block>\n");
+ fz_printf(out, "</block>\n");
}
- fprintf(out, "</page>\n");
+ fz_printf(out, "</page>\n");
}
void
-fz_print_text_page(fz_context *ctx, FILE *out, fz_text_page *page)
+fz_print_text_page(fz_context *ctx, fz_output *out, fz_text_page *page)
{
fz_text_block *block;
fz_text_line *line;
@@ -744,11 +744,11 @@ fz_print_text_page(fz_context *ctx, FILE *out, fz_text_page *page)
{
n = fz_runetochar(utf, ch->c);
for (i = 0; i < n; i++)
- putc(utf[i], out);
+ fz_printf(out, "%c", utf[i]);
}
}
- fprintf(out, "\n");
+ fz_printf(out, "\n");
}
- fprintf(out, "\n");
+ fz_printf(out, "\n");
}
}
diff --git a/fitz/doc_outline.c b/fitz/doc_outline.c
index 71694851..2f23573e 100644
--- a/fitz/doc_outline.c
+++ b/fitz/doc_outline.c
@@ -15,40 +15,40 @@ fz_free_outline(fz_context *ctx, fz_outline *outline)
}
static void
-do_debug_outline_xml(FILE *out, fz_outline *outline, int level)
+do_debug_outline_xml(fz_output *out, fz_outline *outline, int level)
{
while (outline)
{
- fprintf(out, "<outline title=\"%s\" page=\"%d\"", outline->title, outline->dest.kind == FZ_LINK_GOTO ? outline->dest.ld.gotor.page + 1 : 0);
+ fz_printf(out, "<outline title=\"%s\" page=\"%d\"", outline->title, outline->dest.kind == FZ_LINK_GOTO ? outline->dest.ld.gotor.page + 1 : 0);
if (outline->down)
{
- fprintf(out, ">\n");
+ fz_printf(out, ">\n");
do_debug_outline_xml(out, outline->down, level + 1);
- fprintf(out, "</outline>\n");
+ fz_printf(out, "</outline>\n");
}
else
{
- fprintf(out, " />\n");
+ fz_printf(out, " />\n");
}
outline = outline->next;
}
}
void
-fz_print_outline_xml(fz_context *ctx, FILE *out, fz_outline *outline)
+fz_print_outline_xml(fz_context *ctx, fz_output *out, fz_outline *outline)
{
do_debug_outline_xml(out, outline, 0);
}
static void
-do_debug_outline(FILE *out, fz_outline *outline, int level)
+do_debug_outline(fz_output *out, fz_outline *outline, int level)
{
int i;
while (outline)
{
for (i = 0; i < level; i++)
- fputc('\t', out);
- fprintf(out, "%s\t%d\n", outline->title, outline->dest.kind == FZ_LINK_GOTO ? outline->dest.ld.gotor.page + 1 : 0);
+ fz_printf(out, "\t");
+ fz_printf(out, "%s\t%d\n", outline->title, outline->dest.kind == FZ_LINK_GOTO ? outline->dest.ld.gotor.page + 1 : 0);
if (outline->down)
do_debug_outline(out, outline->down, level + 1);
outline = outline->next;
@@ -56,7 +56,7 @@ do_debug_outline(FILE *out, fz_outline *outline, int level)
}
void
-fz_print_outline(fz_context *ctx, FILE *out, fz_outline *outline)
+fz_print_outline(fz_context *ctx, fz_output *out, fz_outline *outline)
{
do_debug_outline(out, outline, 0);
}
diff --git a/fitz/fitz-internal.h b/fitz/fitz-internal.h
index 4839af7d..7e817190 100644
--- a/fitz/fitz-internal.h
+++ b/fitz/fitz-internal.h
@@ -651,11 +651,11 @@ void fz_write_buffer_bits(fz_context *ctx, fz_buffer *buf, int val, int bits);
void fz_write_buffer_pad(fz_context *ctx, fz_buffer *buf);
/*
- fz_buffer_printf: print formatted to a buffer. The buffer will
- grow, but the caller must ensure that no more than 256 bytes are
- added to the buffer per call.
+ fz_buffer_printf: print formatted to a buffer. The buffer will grow
+ as required.
*/
-void fz_buffer_printf(fz_context *ctx, fz_buffer *buffer, const char *fmt, ...);
+int fz_buffer_printf(fz_context *ctx, fz_buffer *buffer, const char *fmt, ...);
+int fz_buffer_vprintf(fz_context *ctx, fz_buffer *buffer, const char *fmt, va_list args);
/*
fz_buffer_printf: print a string formatted as a pdf string to a buffer.
diff --git a/fitz/fitz.h b/fitz/fitz.h
index 43634dd9..b606491a 100644
--- a/fitz/fitz.h
+++ b/fitz/fitz.h
@@ -1784,25 +1784,50 @@ void fz_free_text_sheet(fz_context *ctx, fz_text_sheet *sheet);
fz_text_page *fz_new_text_page(fz_context *ctx, fz_rect mediabox);
void fz_free_text_page(fz_context *ctx, fz_text_page *page);
+typedef struct fz_output_s fz_output;
+
+struct fz_output_s
+{
+ fz_context *ctx;
+ void *opaque;
+ int (*printf)(fz_output *, const char *, va_list ap);
+ void (*close)(fz_output *);
+};
+
+fz_output *fz_new_output_file(fz_context *, FILE *);
+
+fz_output *fz_new_output_buffer(fz_context *, fz_buffer *);
+
+int fz_printf(fz_output *, const char *, ...);
+
+/*
+ fz_close_output: Close a previously opened fz_output stream.
+
+ Note: whether or not this closes the underlying output method is
+ method dependent. FILE * streams created by fz_new_output_file are
+ NOT closed.
+*/
+void fz_close_output(fz_output *);
+
/*
fz_print_text_sheet: Output a text sheet to a file as CSS.
*/
-void fz_print_text_sheet(fz_context *ctx, FILE *out, fz_text_sheet *sheet);
+void fz_print_text_sheet(fz_context *ctx, fz_output *out, fz_text_sheet *sheet);
/*
fz_print_text_page_html: Output a page to a file in HTML format.
*/
-void fz_print_text_page_html(fz_context *ctx, FILE *out, fz_text_page *page);
+void fz_print_text_page_html(fz_context *ctx, fz_output *out, fz_text_page *page);
/*
fz_print_text_page_xml: Output a page to a file in XML format.
*/
-void fz_print_text_page_xml(fz_context *ctx, FILE *out, fz_text_page *page);
+void fz_print_text_page_xml(fz_context *ctx, fz_output *out, fz_text_page *page);
/*
fz_print_text_page: Output a page to a file in UTF-8 format.
*/
-void fz_print_text_page(fz_context *ctx, FILE *out, fz_text_page *page);
+void fz_print_text_page(fz_context *ctx, fz_output *out, fz_text_page *page);
/*
fz_search_text_page: Search for occurrence of 'needle' in text page.
@@ -2149,7 +2174,7 @@ struct fz_outline_s
outline: The outlines to output.
*/
-void fz_print_outline_xml(fz_context *ctx, FILE *out, fz_outline *outline);
+void fz_print_outline_xml(fz_context *ctx, fz_output *out, fz_outline *outline);
/*
fz_print_outline: Dump the given outlines to as text.
@@ -2158,7 +2183,7 @@ void fz_print_outline_xml(fz_context *ctx, FILE *out, fz_outline *outline);
outline: The outlines to output.
*/
-void fz_print_outline(fz_context *ctx, FILE *out, fz_outline *outline);
+void fz_print_outline(fz_context *ctx, fz_output *out, fz_outline *outline);
/*
fz_free_outline: Free hierarchical outline.
diff --git a/fitz/stm_buffer.c b/fitz/stm_buffer.c
index 42a40584..a29f92de 100644
--- a/fitz/stm_buffer.c
+++ b/fitz/stm_buffer.c
@@ -201,19 +201,43 @@ void fz_write_buffer_pad(fz_context *ctx, fz_buffer *buf)
buf->unused_bits = 0;
}
-void
+int
fz_buffer_printf(fz_context *ctx, fz_buffer *buffer, const char *fmt, ...)
{
+ int ret;
va_list args;
va_start(args, fmt);
- /* Caller guarantees not to generate more than 256 bytes per call */
- while(buffer->cap - buffer->len < 256)
+ ret = fz_buffer_vprintf(ctx, buffer, fmt, args);
+
+ va_end(args);
+
+ return ret;
+}
+
+int
+fz_buffer_vprintf(fz_context *ctx, fz_buffer *buffer, const char *fmt, va_list args)
+{
+ int len;
+
+ do
+ {
+ int slack = buffer->cap - buffer->len;
+
+ len = vsnprintf((char *)buffer->data + buffer->len, slack, fmt, args);
+ /* len = number of chars written, not including the terminating
+ * NULL, so len+1 > slack means "truncated". MSVC differs here
+ * and returns -1 for truncated. */
+ if (len > 0 && len+1 <= slack)
+ break;
+ /* Grow the buffer and retry */
fz_grow_buffer(ctx, buffer);
+ }
+ while (1);
- buffer->len += vsprintf((char *)buffer->data + buffer->len, fmt, args);
+ buffer->len += len;
- va_end(args);
+ return len;
}
void
diff --git a/fitz/stm_output.c b/fitz/stm_output.c
new file mode 100644
index 00000000..de3d185e
--- /dev/null
+++ b/fitz/stm_output.c
@@ -0,0 +1,65 @@
+#include "fitz-internal.h"
+
+static int
+file_printf(fz_output *out, const char *fmt, va_list ap)
+{
+ FILE *file = (FILE *)out->opaque;
+
+ return vfprintf(file, fmt, ap);
+}
+
+fz_output *
+fz_new_output_file(fz_context *ctx, FILE *file)
+{
+ fz_output *out = fz_malloc_struct(ctx, fz_output);
+ out->ctx = ctx;
+ out->opaque = file;
+ out->printf = file_printf;
+ out->close = NULL;
+ return out;
+}
+
+void
+fz_close_output(fz_output *out)
+{
+ if (!out)
+ return;
+ if (out->close)
+ out->close(out);
+ fz_free(out->ctx, out);
+}
+
+int
+fz_printf(fz_output *out, const char *fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ if (!out)
+ return 0;
+
+ va_start(ap, fmt);
+ ret = out->printf(out, fmt, ap);
+ va_end(ap);
+
+ return ret;
+}
+
+static int
+buffer_printf(fz_output *out, const char *fmt, va_list list)
+{
+ fz_buffer *buffer = (fz_buffer *)out->opaque;
+
+ return fz_buffer_vprintf(out->ctx, buffer, fmt, list);
+}
+
+fz_output *
+fz_new_output_buffer(fz_context *ctx, fz_buffer *buf)
+{
+ fz_output *out = fz_malloc_struct(ctx, fz_output);
+ out->ctx = ctx;
+ out->opaque = buf;
+ out->printf = buffer_printf;
+ out->close = NULL;
+ return out;
+} \ No newline at end of file