diff options
author | Julian Smith <jules@op59.net> | 2020-09-01 15:50:19 +0100 |
---|---|---|
committer | Julian Smith <jules@op59.net> | 2020-09-01 15:50:19 +0100 |
commit | 3d2eb3182db0451272e428ceb93ed36e118e09fb (patch) | |
tree | 377b12f6b81a4815685e15d1a24db5417a3bb80c | |
parent | aeb5f7f0cb3c3fc569519a99c1d3caad60a9efc1 (diff) |
cosmetic cleanup, including removal of trailing whitespace.
-rw-r--r-- | extract.c | 408 | ||||
-rw-r--r-- | extract.h | 41 |
2 files changed, 297 insertions, 152 deletions
@@ -3,11 +3,6 @@ Extracts text paragraphs from low-level XML representation of text spans, e.g. as generated by 'mutool.py draw -F raw', and creates .docx file containing the text paragraphs. -Build and test with: - ./scripts/ptodoc.py - -Run with -h or --help to see help. - Unless otherwise stated, all functions return 0 on success or -1 with errno set. */ @@ -27,9 +22,16 @@ set. #include <string.h> #include <sys/stat.h> +static const float g_pi = 3.14159265; /* Simple printf-style debug output. */ -void (extract_outf)(const char* file, int line, const char* fn, int ln, const char* format, ...) +void (extract_outf)( + const char* file, int line, + const char* fn, + int ln, + const char* format, + ... + ) { va_list va; if (ln) { @@ -138,7 +140,7 @@ void extract_string_free(extract_string_t* string) int extract_string_catl(extract_string_t* string, const char* s, int s_len) { char* chars = realloc(string->chars, string->chars_num + s_len + 1); - if (!chars) return -1; + if (!chars) return -1; memcpy(chars + string->chars_num, s, s_len); chars[string->chars_num + s_len] = 0; string->chars = chars; @@ -198,7 +200,7 @@ typedef struct { char* name; xml_attribute_t* attributes; int attributes_num; - extract_string_t text; + extract_string_t text; } xml_tag_t; /* Returns pointer to value of specified attribute, or NULL if not found. */ @@ -216,7 +218,11 @@ static char* xml_tag_attributes_find(xml_tag_t* tag, const char* name) /* Finds float value of specified attribute, returning error if not found. We use atof() and don't check for non-numeric attribute value. */ -static int xml_tag_attributes_find_float(xml_tag_t* tag, const char* name, float* o_out) +static int xml_tag_attributes_find_float( + xml_tag_t* tag, + const char* name, + float* o_out + ) { const char* value = xml_tag_attributes_find(tag, name); if (!value) { @@ -227,7 +233,11 @@ static int xml_tag_attributes_find_float(xml_tag_t* tag, const char* name, float return 0; } -static int xml_tag_attributes_find_int(xml_tag_t* tag, const char* name, int* o_out) +static int xml_tag_attributes_find_int( + xml_tag_t* tag, + const char* name, + int* o_out + ) { const char* value = xml_tag_attributes_find(tag, name); if (!value) { @@ -341,7 +351,7 @@ static FILE* xml_pparse_init(const char* path, const char* first_line) size_t first_line_len = strlen(first_line); buffer = malloc(first_line_len + 1); if (!buffer) goto end; - + ssize_t n = fread(buffer, first_line_len, 1 /*nmemb*/, in); if (n != 1) { extract_outf("error: fread() failed. n=%zi. path='%s'", n, path); @@ -541,7 +551,10 @@ static int s_sign(float x) /* Unused but usefult o keep code here. */ #if 0 /* Returns zero if *lhs and *rhs are equal, otherwise +/- 1. */ -static int extract_matrix_cmp(const extract_matrix_t* lhs, const extract_matrix_t* rhs) +static int extract_matrix_cmp( + const extract_matrix_t* lhs, + const extract_matrix_t* rhs + ) { int ret; ret = s_sign(lhs->a - rhs->a); if (ret) return ret; @@ -556,7 +569,10 @@ static int extract_matrix_cmp(const extract_matrix_t* lhs, const extract_matrix_ /* Returns zero if first four members of *lhs and *rhs are equal, otherwise +/-1. */ -static int extract_matrix_cmp4(const extract_matrix_t* lhs, const extract_matrix_t* rhs) +static int extract_matrix_cmp4( + const extract_matrix_t* lhs, + const extract_matrix_t* rhs + ) { int ret; ret = s_sign(lhs->a - rhs->a); if (ret) return ret; @@ -739,7 +755,7 @@ static int docx_char_truncate_if(extract_string_t* content, char c) return 0; } - +/* Like system() but takes printf-style format and args. */ static int systemf(const char* format, ...) { char* command; @@ -755,10 +771,10 @@ static int systemf(const char* format, ...) } int extract_docx_create( - extract_string_t* content, - const char* path_template, - const char* path_out, - int preserve_dir + extract_string_t* content, + const char* path_template, + const char* path_out, + int preserve_dir ) { assert(path_out); @@ -788,7 +804,8 @@ int extract_docx_create( goto end; } - extract_outfx("Unzipping template document '%s' to tempdir: %s", path_template, path_tempdir); + extract_outfx("Unzipping template document '%s' to tempdir: %s", + path_template, path_tempdir); e = systemf("unzip -q -d %s %s", path_tempdir, path_template); if (e) { extract_outf("Failed to unzip %s into %s", @@ -797,7 +814,10 @@ int extract_docx_create( goto end; } - if (local_asprintf(&word_document_xml, "%s/word/document.xml", path_tempdir) < 0) goto end; + if (local_asprintf( + &word_document_xml, + "%s/word/document.xml", + path_tempdir) < 0) goto end; extract_outfx("Reading tempdir's word/document.xml object"); f = fopen(word_document_xml, "r"); @@ -823,13 +843,14 @@ int extract_docx_create( extract_outfx("Writing tempdir's word/document.xml file"); f = fopen(word_document_xml, "w"); if (!f) { - extract_outf("error: Failed to open .docx for writing: %s", word_document_xml); + extract_outf("error: Failed to open .docx for writing: %s", + word_document_xml); goto end; } if (0 - || fwrite(original, original_pos - original, 1 /*nmemb*/, f) == 0 - || fwrite(content->chars, content->chars_num, 1 /*nmemb*/, f) == 0 - || fwrite(original_pos, strlen(original_pos), 1 /*nmemb*/, f) == 0 + || fwrite(original, original_pos - original, 1 /*nmemb*/, f) != 1 + || fwrite(content->chars, content->chars_num, 1 /*nmemb*/, f) != 1 + || fwrite(original_pos, strlen(original_pos), 1 /*nmemb*/, f) != 1 || fclose(f) < 0 ) { extract_outf("error: Failed to write to: %s", word_document_xml); @@ -921,7 +942,14 @@ const char* extract_span_string(extract_span_t* span) extract_string_cat(&ret, buffer); int i; for (i=0; i<span->chars_num; ++i) { - snprintf(buffer, sizeof(buffer), " i=%i {x=%f adv=%f}", i, span->chars[i].x, span->chars[i].adv); + snprintf( + buffer, + sizeof(buffer), + " i=%i {x=%f adv=%f}", + i, + span->chars[i].x, + span->chars[i].adv + ); extract_string_cat(&ret, buffer); } extract_string_cat(&ret, ": "); @@ -947,10 +975,14 @@ const char* extract_span_string2(extract_span_t* span) return ret.chars; } -/* Appends new extract_char_t a extract_span_t with .ucs=c and all other fields zeroed. */ +/* Appends new extract_char_t to an extract_span_t with .ucs=c and all other +fields zeroed. */ static int extract_span_append_c(extract_span_t* span, int c) { - extract_char_t* items = realloc(span->chars, sizeof(*items) * (span->chars_num + 1)); + extract_char_t* items = realloc( + span->chars, + sizeof(*items) * (span->chars_num + 1) + ); if (!items) return -1; span->chars = items; extract_char_t* item = &span->chars[span->chars_num]; @@ -1048,21 +1080,28 @@ static const char* extract_paragraph_string(extract_paragraph_t* paragraph) extract_string_cat(&ret, extract_line_string2(paragraph->lines[0])); if (paragraph->lines_num > 1) { extract_string_cat(&ret, ".."); - extract_string_cat(&ret, extract_line_string2(paragraph->lines[paragraph->lines_num-1])); + extract_string_cat( + &ret, + extract_line_string2(paragraph->lines[paragraph->lines_num-1]) + ); } } return ret.chars; } /* Returns first line in paragraph. */ -static extract_line_t* extract_paragraph_line_first(const extract_paragraph_t* paragraph) +static extract_line_t* extract_paragraph_line_first( + const extract_paragraph_t* paragraph + ) { assert(paragraph->lines_num); return paragraph->lines[0]; } /* Returns last line in paragraph. */ -static extract_line_t* extract_paragraph_line_last(const extract_paragraph_t* paragraph) +static extract_line_t* extract_paragraph_line_last( + const extract_paragraph_t* paragraph + ) { assert(paragraph->lines_num); return paragraph->lines[ paragraph->lines_num-1]; @@ -1108,7 +1147,11 @@ float extract_span_adv_total(extract_span_t* span) } /* Returns distance between end of <a> and beginning of <b>. */ -static float spans_adv(extract_span_t* a_span, extract_char_t* a, extract_char_t* b) +static float spans_adv( + extract_span_t* a_span, + extract_char_t* a, + extract_char_t* b + ) { float delta_x = b->x - a->x; float delta_y = b->y - a->y; @@ -1119,12 +1162,22 @@ static float spans_adv(extract_span_t* a_span, extract_char_t* a, extract_char_t } /* Returns 1 if lines have same wmode and are at the same angle, else 0. */ -static int lines_are_compatible(extract_line_t* a, extract_line_t* b, float angle_a, int verbose) +static int lines_are_compatible( + extract_line_t* a, + extract_line_t* b, + float angle_a, + int verbose + ) { if (a == b) return 0; if (!a->spans || !b->spans) return 0; - if (extract_line_span_first(a)->wmode != extract_line_span_first(b)->wmode) return 0; - if (extract_matrix_cmp4(&extract_line_span_first(a)->ctm, &extract_line_span_first(b)->ctm)) { + if (extract_line_span_first(a)->wmode != extract_line_span_first(b)->wmode) { + return 0; + } + if (extract_matrix_cmp4( + &extract_line_span_first(a)->ctm, + &extract_line_span_first(b)->ctm + )) { if (verbose) { extract_outf("ctm's differ:"); extract_outf(" %f %f %f %f %f %f", @@ -1155,35 +1208,36 @@ static int lines_are_compatible(extract_line_t* a, extract_line_t* b, float angl } -/* Creates representation of extract_span_t's that consists of a list of extract_line_t's, with -each extract_line_t containins pointers to a list of extract_span_t's. +/* Creates representation of extract_span_t's that consists of a list of +extract_line_t's, with each extract_line_t containins pointers to a list of +extract_span_t's. We only join spans that are at the same angle and are aligned. On entry: Original value of *o_lines and *o_lines_num are ignored. - <spans> points to array of <spans_num> extract_span_t*'s, each pointing to a - extract_span_t. + <spans> points to array of <spans_num> extract_span_t*'s, each pointing to + an extract_span_t. On exit: If we succeed, we return 0, with *o_lines pointing to array of *o_lines_num - extract_line_t*'s, each pointing to a extract_line_t. + extract_line_t*'s, each pointing to an extract_line_t. Otherwise we return -1 with errno set. *o_lines and *o_lines_num are undefined. */ static int make_lines( - extract_span_t** spans, - int spans_num, - extract_line_t*** o_lines, - int* o_lines_num + extract_span_t** spans, + int spans_num, + extract_line_t*** o_lines, + int* o_lines_num ) { int ret = -1; - /* Make a extract_line_t for each span. Then we will join some of these extract_line_t's - together before returning. */ + /* Make an extract_line_t for each span. Then we will join some of these + extract_line_t's together before returning. */ int lines_num = spans_num; extract_line_t** lines = NULL; @@ -1205,7 +1259,7 @@ static int make_lines( lines[a]->spans[0] = spans[a]; extract_outfx("initial line a=%i: %s", a, extract_line_string(lines[a])); } - + int num_compatible = 0; /* For each line, look for nearest aligned line, and append if found. */ @@ -1228,7 +1282,7 @@ static int make_lines( float angle_a = extract_span_angle(span_a); if (verbose) extract_outf("a=%i angle_a=%lf ctm=%s: %s", a, - angle_a * 180/3.1415926, + angle_a * 180/g_pi, extract_matrix_string(&span_a->ctm), extract_line_string2(line_a) ); @@ -1259,7 +1313,6 @@ static int make_lines( } num_compatible += 1; - const float pi = 3.14159265; /* Find angle between last glyph of extract_span_a and first glyph of extract_span_b. This detects whether the lines are lined up with each other @@ -1276,16 +1329,20 @@ static int make_lines( extract_span_char_last(span_a)->y, extract_span_char_first(span_b)->x, extract_span_char_first(span_b)->y, - angle_a * 180 / pi, - angle_a_b * 180 / pi + angle_a * 180 / g_pi, + angle_a_b * 180 / g_pi ); } /* Might want to relax this when we test on non-horizontal lines. */ const float angle_tolerance_deg = 1; - if (fabs(angle_a_b - angle_a) * 180/pi <= angle_tolerance_deg) { + if (fabs(angle_a_b - angle_a) * 180 / g_pi <= angle_tolerance_deg) { /* Find distance between end of extract_line_a and beginning of extract_line_b. */ - float adv = spans_adv(span_a, extract_span_char_last(span_a), extract_span_char_first(span_b)); + float adv = spans_adv( + span_a, + extract_span_char_last(span_a), + extract_span_char_first(span_b) + ); if (verbose) extract_outf("nearest_adv=%lf. angle_a_b=%lf adv=%lf", nearest_adv, angle_a_b, @@ -1304,8 +1361,8 @@ static int make_lines( extract_span_char_last(span_a)->y, extract_span_char_first(span_b)->x, extract_span_char_first(span_b)->y, - angle_a_b * 180/pi, - angle_a * 180/pi, + angle_a_b * 180 / g_pi, + angle_a * 180 / g_pi, span_a->trm.a, span_a->trm.b ); @@ -1313,8 +1370,8 @@ static int make_lines( } if (nearest_line) { - /* extract_line_a and nearest_line are aligned so we can move extract_line_b's spans on - to the end of extract_line_a. */ + /* extract_line_a and nearest_line are aligned so we can move + extract_line_b's spans on to the end of extract_line_a. */ b = nearest_line_b; if (verbose) extract_outf("found nearest line. a=%i b=%i", a, b); extract_span_t* span_b = extract_line_span_first(nearest_line); @@ -1344,7 +1401,10 @@ static int make_lines( extract_outf(" a: %s", extract_span_string(span_a)); extract_outf(" b: %s", extract_span_string(span_b)); } - extract_char_t* p = realloc(span_a->chars, (span_a->chars_num + 1) * sizeof(extract_char_t)); + extract_char_t* p = realloc( + span_a->chars, + (span_a->chars_num + 1) * sizeof(extract_char_t) + ); if (!p) goto end; span_a->chars = p; extract_char_t* item = &span_a->chars[span_a->chars_num]; @@ -1387,7 +1447,8 @@ static int make_lines( } extract_span_t** s = realloc( line_a->spans, - sizeof(extract_span_t*) * (line_a->spans_num + nearest_line->spans_num) + sizeof(extract_span_t*) + * (line_a->spans_num + nearest_line->spans_num) ); if (!s) goto end; line_a->spans = s; @@ -1407,7 +1468,7 @@ static int make_lines( if (b > a) { /* We haven't yet tried appending any spans to nearest_line, so - the new extended extract_line_a needs checking again. */ + the new extended line_a needs checking again. */ a -= 1; } extract_outfx("new line is:\n %s", extract_line_string2(line_a)); @@ -1429,7 +1490,9 @@ static int make_lines( } lines_num = to; extract_line_t** l = realloc(lines, sizeof(extract_line_t*) * lines_num); - assert(l); /* Should always succeed because we're not increasing allocation size. */ + /* Should always succeed because we're not increasing allocation size. */ + assert(l); + lines = l; *o_lines = lines; @@ -1454,7 +1517,7 @@ static int make_lines( } -/* Returns max font size of all extract_span_t's in a extract_line_t. */ +/* Returns max font size of all extract_span_t's in an extract_line_t. */ static float extract_line_font_size_max(extract_line_t* line) { float size_max = 0; @@ -1471,7 +1534,7 @@ static float extract_line_font_size_max(extract_line_t* line) -/* Find distance between parallel lines extract_line_a and extract_line_b, both at <angle>. +/* Find distance between parallel lines line_a and line_b, both at <angle>. _-R _- @@ -1490,14 +1553,21 @@ respectively. AQB is a right angle. We need to find AQ. */ -static float extract_line_distance(float ax, float ay, float bx, float by, float angle) +static float extract_line_distance( + float ax, + float ay, + float bx, + float by, + float angle + ) { float dx = bx - ax; float dy = by - ay; - + return dx * sin(angle) + dy * cos(angle); } + /* A comparison function for use with qsort(), for sorting paragraphs within a page. */ static int paragraphs_cmp(const void* a, const void* b) @@ -1533,36 +1603,37 @@ static int paragraphs_cmp(const void* a, const void* b) return 0; } + /* Creates a representation of extract_line_t's that consists of a list of -paragraph_t's. +extract_paragraph_t's. We only join lines that are at the same angle and are adjacent. On entry: Original value of *o_paragraphs and *o_paragraphs_num are ignored. - <lines> points to array of <lines_num> extract_line_t*'s, each pointing to a - extract_line_t. + <lines> points to array of <lines_num> extract_line_t*'s, each pointing to + a extract_line_t. On exit: On sucess, returns zero, *o_paragraphs points to array of *o_paragraphs_num - extract_paragraph_t*'s, each pointing to a extract_paragraph_t. In the array, extract_paragraph_t's - with same angle are sorted. + extract_paragraph_t*'s, each pointing to an extract_paragraph_t. In the + array, extract_paragraph_t's with same angle are sorted. On failure, returns -1 with errno set. *o_paragraphs and *o_paragraphs_num are undefined. */ static int make_paragraphs( - extract_line_t** lines, - int lines_num, - extract_paragraph_t*** o_paragraphs, - int* o_paragraphs_num + extract_line_t** lines, + int lines_num, + extract_paragraph_t*** o_paragraphs, + int* o_paragraphs_num ) { int ret = -1; extract_paragraph_t** paragraphs = NULL; - /* Start off with a extract_paragraph_t for each extract_line_t. */ + /* Start off with an extract_paragraph_t for each extract_line_t. */ int paragraphs_num = lines_num; paragraphs = malloc(sizeof(*paragraphs) * paragraphs_num); if (!paragraphs) goto end; @@ -1599,11 +1670,11 @@ static int make_paragraphs( extract_line_t* line_a = extract_paragraph_line_last(paragraph_a); float angle_a = extract_line_angle(line_a); - + int verbose = 0; - /* Look for nearest extract_paragraph_t that could be appended to extract_paragraph_a. - */ + /* Look for nearest extract_paragraph_t that could be appended to + paragraph_a. */ int b; for (b=0; b<paragraphs_num; ++b) { extract_paragraph_t* paragraph_b = paragraphs[b]; @@ -1623,8 +1694,9 @@ static int make_paragraphs( float by = extract_line_item_first(line_b)->y; float distance = extract_line_distance(ax, ay, bx, by, angle_a); if (verbose) { - extract_outf("angle_a=%lf a=(%lf %lf) b=(%lf %lf) delta=(%lf %lf) distance=%lf:", - angle_a * 180 / 3.1415926, + extract_outf( + "angle_a=%lf a=(%lf %lf) b=(%lf %lf) delta=(%lf %lf) distance=%lf:", + angle_a * 180 / g_pi, ax, ay, bx, by, bx - ax, @@ -1652,7 +1724,9 @@ static int make_paragraphs( if (nearest_paragraph) { extract_line_t* line_b = extract_paragraph_line_first(nearest_paragraph); (void) line_b; /* Only used in extract_outfx(). */ - float line_b_size = extract_line_font_size_max(extract_paragraph_line_first(nearest_paragraph)); + float line_b_size = extract_line_font_size_max( + extract_paragraph_line_first(nearest_paragraph) + ); if (nearest_paragraph_distance < 1.5 * line_b_size) { if (verbose) { extract_outf( @@ -1666,8 +1740,12 @@ static int make_paragraphs( ); extract_outf(" %s", extract_paragraph_string(paragraph_a)); extract_outf(" %s", extract_paragraph_string(nearest_paragraph)); - extract_outf("paragraph_a ctm=%s", extract_matrix_string(¶graph_a->lines[0]->spans[0]->ctm)); - extract_outf("paragraph_a trm=%s", extract_matrix_string(¶graph_a->lines[0]->spans[0]->trm)); + extract_outf("paragraph_a ctm=%s", + extract_matrix_string(¶graph_a->lines[0]->spans[0]->ctm) + ); + extract_outf("paragraph_a trm=%s", + extract_matrix_string(¶graph_a->lines[0]->spans[0]->trm) + ); } /* Join these two extract_paragraph_t's. */ extract_span_t* a_span = extract_line_span_last(line_a); @@ -1682,12 +1760,16 @@ static int make_paragraphs( } int a_lines_num_new = paragraph_a->lines_num + nearest_paragraph->lines_num; - extract_line_t** l = realloc(paragraph_a->lines, sizeof(extract_line_t*) * a_lines_num_new); + extract_line_t** l = realloc( + paragraph_a->lines, + sizeof(extract_line_t*) * a_lines_num_new + ); if (!l) goto end; paragraph_a->lines = l; int i; for (i=0; i<nearest_paragraph->lines_num; ++i) { - paragraph_a->lines[paragraph_a->lines_num + i] = nearest_paragraph->lines[i]; + paragraph_a->lines[paragraph_a->lines_num + i] + = nearest_paragraph->lines[i]; } paragraph_a->lines_num = a_lines_num_new; @@ -1697,7 +1779,8 @@ static int make_paragraphs( paragraphs[nearest_paragraph_b] = NULL; num_joins += 1; - extract_outfx("have joined paragraph a=%i to snearest_paragraph_b=%i", + extract_outfx( + "have joined paragraph a=%i to snearest_paragraph_b=%i", a, nearest_paragraph_b ); @@ -1710,8 +1793,11 @@ static int make_paragraphs( } } else { - extract_outfx("Not joining paragraphs. nearest_paragraph_distance=%lf extract_line_b_size=%lf", - nearest_paragraph_distance, extract_line_b_size); + extract_outfx( + "Not joining paragraphs. nearest_paragraph_distance=%lf extract_line_b_size=%lf", + nearest_paragraph_distance, + extract_line_b_size + ); } } } @@ -1727,13 +1813,22 @@ static int make_paragraphs( } extract_outfx("paragraphs_num=%i => %i", paragraphs_num, to); paragraphs_num = to; - extract_paragraph_t** p = realloc(paragraphs, sizeof(extract_paragraph_t*) * paragraphs_num); - assert(p); /* Should always succeed because we're not increasing allocation size. */ + extract_paragraph_t** p = realloc( + paragraphs, + sizeof(extract_paragraph_t*) * paragraphs_num + ); + /* Should always succeed because we're not increasing allocation size. */ + assert(p); + paragraphs = p; /* Sort paragraphs so they appear in correct order, using paragraphs_cmp(). */ - qsort(paragraphs, paragraphs_num, sizeof(extract_paragraph_t*), paragraphs_cmp); + qsort( + paragraphs, + paragraphs_num, + sizeof(extract_paragraph_t*), paragraphs_cmp + ); *o_paragraphs = paragraphs; *o_paragraphs_num = paragraphs_num; @@ -1801,8 +1896,8 @@ static void extract_page_free(extract_page_t* page) free(page->paragraphs); } -/* Appends new empty extract_span_ to a extract_page_t; returns NULL with errno set on error. -*/ +/* Appends new empty extract_span_ to an extract_page_t; returns NULL with +errno set on error. */ static extract_span_t* extract_page_span_append(extract_page_t* page) { extract_span_t* span = malloc(sizeof(*span)); @@ -1810,7 +1905,10 @@ static extract_span_t* extract_page_span_append(extract_page_t* page) span->font_name = NULL; span->chars = NULL; span->chars_num = 0; - extract_span_t** s = realloc(page->spans, sizeof(*s) * (page->spans_num + 1)); + extract_span_t** s = realloc( + page->spans, + sizeof(*s) * (page->spans_num + 1) + ); if (!s) { free(span); return NULL; @@ -1827,9 +1925,11 @@ void extract_document_init(extract_document_t* document) document->pages_num = 0; } -/* Appends new empty extract_page_t to a extract_document_t; returns NULL with errno set on +/* Appends new empty extract_page_t to an extract_document_t; returns NULL with errno set on error. */ -static extract_page_t* extract_document_page_append(extract_document_t* document) +static extract_page_t* extract_document_page_append( + extract_document_t* document + ) { extract_page_t* page = malloc(sizeof(extract_page_t)); if (!page) return NULL; @@ -1839,7 +1939,10 @@ static extract_page_t* extract_document_page_append(extract_document_t* document page->lines_num = 0; page->paragraphs = NULL; page->paragraphs_num = 0; - extract_page_t** pages = realloc(document->pages, sizeof(extract_page_t*) * (document->pages_num + 1)); + extract_page_t** pages = realloc( + document->pages, + sizeof(extract_page_t*) * (document->pages_num + 1) + ); if (!pages) { free(page); return NULL; @@ -1867,9 +1970,9 @@ void extract_document_free(extract_document_t* document) /* Does preliminary processing of the end of the last spen in a page; intended to be called as we load span information. -Looks at last two extract_char_t's in last extract_span_t of <page>, and either leaves -unchanged, or removes space in last-but-one position, or moves last extract_char_t into -a new extract_span_t. */ +Looks at last two extract_char_t's in last extract_span_t of <page>, and either +leaves unchanged, or removes space in last-but-one position, or moves last +extract_char_t into a new extract_span_t. */ static int extract_page_span_end_clean(extract_page_t* page) { int ret = -1; @@ -1884,7 +1987,8 @@ static int extract_page_span_end_clean(extract_page_t* page) return 0; } - float font_size = extract_matrix_expansion(span->trm) * extract_matrix_expansion(span->ctm); + float font_size = extract_matrix_expansion(span->trm) + * extract_matrix_expansion(span->ctm); point_t dir; if (span->wmode) { @@ -1902,7 +2006,7 @@ static int extract_page_span_end_clean(extract_page_t* page) float err_x = (char_[-1].pre_x - x) / font_size; float err_y = (char_[-1].pre_y - y) / font_size; - + if (span->chars_num >= 2 && span->chars[span->chars_num-2].ucs == ' ') { int remove_penultimate_space = 0; if (err_x < -span->chars[span->chars_num-2].adv / 2 @@ -1911,9 +2015,11 @@ static int extract_page_span_end_clean(extract_page_t* page) remove_penultimate_space = 1; } if ((char_[-1].pre_x - char_[-2].pre_x) / font_size < char_[-1].adv / 10) { - extract_outfx("removing penultimate space because space very narrow:" - "char_[-1].pre_x-char_[-2].pre_x=%f font_size=%f extract_char_[-1].adv=%f", - extract_char_[-1].pre_x-char_[-2].pre_x, + extract_outfx( + "removing penultimate space because space very narrow:" + "char_[-1].pre_x-char_[-2].pre_x=%f font_size=%f" + " extract_char_[-1].adv=%f", + extract_char_[-1].pre_x - char_[-2].pre_x, font_size, char_[-1].adv ); @@ -1924,7 +2030,8 @@ static int extract_page_span_end_clean(extract_page_t* page) character. We discard previous space character - these sometimes seem to appear in the middle of words for some reason. */ - extract_outfx("removing space before final char in: %s", extract_span_string(span)); + extract_outfx("removing space before final char in: %s", + extract_span_string(span)); span->chars[span->chars_num-2] = span->chars[span->chars_num-1]; span->chars_num -= 1; extract_outfx("span is now: %s", extract_span_string(span)); @@ -1936,7 +2043,9 @@ static int extract_page_span_end_clean(extract_page_t* page) previous characters, so split into two spans. This often splits text incorrectly, but this is corrected later when we join spans into lines. */ - extract_outfx("Splitting last char into new span. font_size=%f dir.x=%f char[-1].pre=(%f, %f) err=(%f, %f): %s", + extract_outfx( + "Splitting last char into new span. font_size=%f dir.x=%f" + " char[-1].pre=(%f, %f) err=(%f, %f): %s", font_size, dir.x, extract_char_[-1].pre_x, @@ -1963,9 +2072,9 @@ static int extract_page_span_end_clean(extract_page_t* page) } int extract_read_spans_raw( - const char* path, + const char* path, extract_document_t* document, - int autosplit + int autosplit ) { int ret = -1; @@ -1973,8 +2082,12 @@ int extract_read_spans_raw( FILE* in = NULL; extract_document_init(document); int num_spans = 0; - int num_spans_split = 0; /* Num extra spns from extract_page_span_end_clean(). */ - int num_spans_autosplit = 0; /* Num extra spans from autosplit=1. */ + + /* Num extra spns from extract_page_span_end_clean(). */ + int num_spans_split = 0; + + /* Num extra spans from autosplit=1. */ + int num_spans_autosplit = 0; xml_tag_t tag; xml_tag_init(&tag); @@ -2043,10 +2156,10 @@ int extract_read_spans_raw( extract_span_t* span = extract_page_span_append(page); if (!span) goto end; - + if (s_matrix_read(xml_tag_attributes_find(&tag, "ctm"), &span->ctm)) goto end; if (s_matrix_read(xml_tag_attributes_find(&tag, "trm"), &span->trm)) goto end; - + char* f = xml_tag_attributes_find(&tag, "font_name"); if (!f) { extract_outf("Failed to find attribute 'font_name'"); @@ -2081,19 +2194,23 @@ int extract_read_spans_raw( extract_outf("Expected <char> but tag.name='%s'", tag.name); goto end; } - + float char_pre_x; float char_pre_y; if (xml_tag_attributes_find_float(&tag, "x", &char_pre_x)) goto end; if (xml_tag_attributes_find_float(&tag, "y", &char_pre_y)) goto end; - + if (autosplit && char_pre_y - offset_y != 0) { - extract_outfx("autosplit: extract_char_pre_y=%f offset_y=%f", extract_char_pre_y, offset_y); - float e = span->ctm.e + span->ctm.a * (char_pre_x-offset_x) + span->ctm.b * (char_pre_y-offset_y); - float f = span->ctm.f + span->ctm.c * (char_pre_x-offset_x) + span->ctm.d * (char_pre_y-offset_y); + extract_outfx("autosplit: extract_char_pre_y=%f offset_y=%f", + extract_char_pre_y, offset_y); + float e = span->ctm.e + span->ctm.a * (char_pre_x-offset_x) + + span->ctm.b * (char_pre_y - offset_y); + float f = span->ctm.f + span->ctm.c * (char_pre_x-offset_x) + + span->ctm.d * (char_pre_y - offset_y); offset_x = char_pre_x; offset_y = char_pre_y; - extract_outfx("autosplit: changing ctm.{e,f} from (%f, %f) to (%f, %f)", + extract_outfx( + "autosplit: changing ctm.{e,f} from (%f, %f) to (%f, %f)", span->ctm.e, span->ctm.f, e, f @@ -2112,30 +2229,34 @@ int extract_read_spans_raw( } span->ctm.e = e; span->ctm.f = f; - extract_outfx("autosplit: extract_char_pre_y=%f offset_y=%f", extract_char_pre_y, offset_y); + extract_outfx("autosplit: extract_char_pre_y=%f offset_y=%f", + extract_char_pre_y, offset_y); } - + if (extract_span_append_c(span, 0 /*c*/)) goto end; extract_char_t* char_ = &span->chars[ span->chars_num-1]; char_->pre_x = char_pre_x - offset_x; char_->pre_y = char_pre_y - offset_y; if (char_->pre_y) { - extract_outfx("char_->pre=(%f %f)", char_->pre_x, char_->pre_y); + extract_outfx("char_->pre=(%f %f)", + char_->pre_x, char_->pre_y); } char_->x = span->ctm.a * char_->pre_x + span->ctm.b * char_->pre_y; char_->y = span->ctm.c * char_->pre_x + span->ctm.d * char_->pre_y; if (xml_tag_attributes_find_float(&tag, "adv", &char_->adv)) goto end; - + if (xml_tag_attributes_find_int(&tag, "ucs", &char_->ucs)) goto end; char trm[64]; snprintf(trm, sizeof(trm), "%s", extract_matrix_string(&span->trm)); char_->x += span->ctm.e; char_->y += span->ctm.f; - - extract_outfx("ctm=%s trm=%s ctm*trm=%f pre=(%f %f) => xy=(%f %f) [orig xy=(%f %f)]", + + extract_outfx( + "ctm=%s trm=%s ctm*trm=%f pre=(%f %f) =>" + " xy=(%f %f) [orig xy=(%f %f)]", extract_matrix_string(&span->ctm), trm, span->ctm.a * span->trm.a, @@ -2143,7 +2264,7 @@ int extract_read_spans_raw( extract_char_->x, extract_char_->y, x, y ); - + int page_spans_num_old = page->spans_num; if (extract_page_span_end_clean(page)) goto end; span = page->spans[page->spans_num-1]; @@ -2153,9 +2274,10 @@ int extract_read_spans_raw( } xml_tag_free(&tag); } - extract_outf("page=%i page->num_spans=%i", document->pages_num, page->spans_num); + extract_outf("page=%i page->num_spans=%i", + document->pages_num, page->spans_num); } - + extract_outf("num_spans=%i num_spans_split=%i num_spans_autosplit=%i", num_spans, num_spans_split, @@ -2182,7 +2304,8 @@ int extract_read_spans_raw( static float matrices_to_font_size(extract_matrix_t* ctm, extract_matrix_t* trm) { - float font_size = extract_matrix_expansion(*trm) * extract_matrix_expansion(*ctm); + float font_size = extract_matrix_expansion(*trm) + * extract_matrix_expansion(*ctm); /* Round font_size to nearest 0.01. */ font_size = (int) (font_size * 100 + 0.5) / 100.0; return font_size; @@ -2192,7 +2315,11 @@ static float matrices_to_font_size(extract_matrix_t* ctm, extract_matrix_t* trm) points to zero-terminated content, allocated by realloc(). spacing: if true, we insert extra vertical space between paragraphs. */ -static int paragraphs_to_content(extract_document_t* document, extract_string_t* content, int spacing) +static int paragraphs_to_content( + extract_document_t* document, + extract_string_t* content, + int spacing + ) { int ret = -1; @@ -2213,7 +2340,10 @@ static int paragraphs_to_content(extract_document_t* document, extract_string_t* && ctm_prev && paragraph->lines_num && paragraph->lines[0]->spans_num - && extract_matrix_cmp4(ctm_prev, ¶graph->lines[0]->spans[0]->ctm) + && extract_matrix_cmp4( + ctm_prev, + ¶graph->lines[0]->spans[0]->ctm + ) ) { /* Extra vertical space between paragraphs that were at different angles in the original document. */ @@ -2233,7 +2363,9 @@ static int paragraphs_to_content(extract_document_t* document, extract_string_t* for (s=0; s<line->spans_num; ++s) { extract_span_t* span = line->spans[s]; ctm_prev = &span->ctm; - float font_size_new = matrices_to_font_size(&span->ctm, &span->trm); + float font_size_new = matrices_to_font_size( + &span->ctm, &span->trm + ); if (!font_name || strcmp(span->font_name, font_name) || span->font_bold != font_bold @@ -2247,7 +2379,13 @@ static int paragraphs_to_content(extract_document_t* document, extract_string_t* font_bold = span->font_bold; font_italic = span->font_italic; font_size = font_size_new; - if (docx_run_start(content, font_name, font_size, font_bold, font_italic)) goto end; + if (docx_run_start( + content, + font_name, + font_size, + font_bold, + font_italic + )) goto end; } int si; @@ -2256,7 +2394,7 @@ static int paragraphs_to_content(extract_document_t* document, extract_string_t* int c = extract_char_->ucs; if (0) {} - + /* Escape XML special characters. */ else if (c == '<') docx_char_append_string(content, "<"); else if (c == '>') docx_char_append_string(content, ">"); @@ -2318,8 +2456,8 @@ static int paragraphs_to_content(extract_document_t* document, extract_string_t* *content points to zero-terminated content, allocated by realloc(). */ int extract_document_to_docx_content( extract_document_t* document, - extract_string_t* content, - int spacing + extract_string_t* content, + int spacing ) { int ret = -1; @@ -5,7 +5,15 @@ Unless otherwise stated, all functions return 0 on success or -1 with errno set. */ -void extract_outf(const char* file, int line, const char* fn, int ln, const char* format, ...); +/* Simple debug output. */ +void (extract_outf)( + const char* file, int line, + const char* fn, + int ln, + const char* format, + ... + ) +; #define extract_outf(format, ...) (extract_outf)(__FILE__, __LINE__, __FUNCTION__, 1 /*ln*/, format, ##__VA_ARGS__) #define extract_outfx(format, ...) @@ -71,7 +79,7 @@ typedef struct extract_span_t typedef struct { extract_span_t** spans; - int spans_num; + int spans_num; } extract_line_t; /* A list of lines that are aligned and adjacent to each other so as to form a @@ -79,27 +87,27 @@ paragraph. */ typedef struct { extract_line_t** lines; - int lines_num; + int lines_num; } extract_paragraph_t; /* A page. */ typedef struct { - extract_span_t** spans; - int spans_num; + extract_span_t** spans; + int spans_num; /* .lines[] eventually points to items in .spans. */ - extract_line_t** lines; - int lines_num; + extract_line_t** lines; + int lines_num; /* .paragraphs[] eventually points to items in .lines. */ extract_paragraph_t** paragraphs; - int paragraphs_num; + int paragraphs_num; } extract_page_t; typedef struct { extract_page_t** pages; - int pages_num; + int pages_num; } extract_document_t; void extract_document_init(extract_document_t* document); @@ -122,8 +130,8 @@ int extract_read_spans_raw( *content points to zero-terminated content, allocated by realloc(). */ int extract_document_to_docx_content( extract_document_t* document, - extract_string_t* content, - int spacing + extract_string_t* content, + int spacing ); /* @@ -142,12 +150,11 @@ preserve_dir: Returns 0 on success or -1 with errno set. -We use the 'zip' and 'unzip' commands. +Uses the 'zip' and 'unzip' commands internally. */ - int extract_docx_create( - extract_string_t* content, - const char* path_template, - const char* path_out, - int preserve_dir + extract_string_t* content, + const char* path_template, + const char* path_out, + int preserve_dir ); |