CMakeLists.txt | 2 glib/CMakeLists.txt | 1 glib/poppler-page.cc | 48 ++++++ glib/poppler-page.h | 3 glib/reference/poppler-sections.txt | 1 glib/tests/CMakeLists.txt | 43 ++++++ glib/tests/check_bb.c | 92 +++++++++++++ glib/tests/check_text.c | 55 +++++++ glib/tests/pdfdrawbb.c | 143 ++++++++++++++++++++ poppler/BBoxOutputDev.cc | 251 ++++++++++++++++++++++++++++++++++++ poppler/BBoxOutputDev.h | 73 ++++++++++ 11 files changed, 712 insertions(+)
New commits: commit 967a21b5c2bedd0c0debb74ae622edbc1a5b486a Author: sgerwk <[email protected]> Date: Wed Apr 1 21:53:58 2020 +0000 bounding box of graphics in the page diff --git a/CMakeLists.txt b/CMakeLists.txt index 28d46c4d..dbe6a089 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -404,6 +404,7 @@ set(poppler_SRCS poppler/Movie.cc poppler/Rendition.cc poppler/CertificateInfo.cc + poppler/BBoxOutputDev.cc ) set(poppler_LIBS ${FREETYPE_LIBRARIES}) if(ENABLE_SPLASH) @@ -614,6 +615,7 @@ if(ENABLE_UNSTABLE_API_ABI_HEADERS) poppler/SecurityHandler.h poppler/StdinCachedFile.h poppler/StdinPDFDocBuilder.h + poppler/BBoxOutputDev.h poppler/UTF.h poppler/Sound.h ${CMAKE_CURRENT_BINARY_DIR}/poppler/poppler-config.h diff --git a/glib/CMakeLists.txt b/glib/CMakeLists.txt index 2781f091..c5aaea6f 100644 --- a/glib/CMakeLists.txt +++ b/glib/CMakeLists.txt @@ -20,6 +20,7 @@ configure_file(poppler-features.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/poppler-feat if (GTK_FOUND AND BUILD_GTK_TESTS) add_subdirectory(demo) + add_subdirectory(tests) endif () set(poppler_glib_public_headers diff --git a/glib/poppler-page.cc b/glib/poppler-page.cc index 322f2d48..7ae9463e 100644 --- a/glib/poppler-page.cc +++ b/glib/poppler-page.cc @@ -27,6 +27,7 @@ #include <UnicodeMap.h> #include <GfxState.h> #include <PageTransition.h> +#include <BBoxOutputDev.h> #endif #include "poppler.h" @@ -2187,6 +2188,53 @@ poppler_page_get_crop_box (PopplerPage *page, PopplerRectangle *rect) rect->y2 = cropBox->y2; } +/* + * poppler_page_get_bounding_box: + * @page: A #PopplerPage + * @rect: (out) return the bounding box of the page + * + * Returns the bounding box of the page, a rectangle enclosing all text, vector + * graphics (lines, rectangles and curves) and raster images in the page. + * Includes invisible text but not (yet) annotations like highlights and form + * elements. + * + * Return value: %TRUE if the page contains graphics, %FALSE otherwise + * + * Since: 0.88 + */ +gboolean +poppler_page_get_bounding_box (PopplerPage *page, + PopplerRectangle *rect) { + Gfx *gfx; + BBoxOutputDev *bb_out; + bool hasGraphics; + + g_return_val_if_fail(POPPLER_IS_PAGE (page), false); + g_return_val_if_fail(rect != nullptr, false); + + bb_out = new BBoxOutputDev(page->page->getCropBox()); + + gfx = page->page->createGfx(bb_out, + 72.0, 72.0, 0, + false, /* useMediaBox */ + true, /* Crop */ + -1, -1, -1, -1, + false, /* printing */ + nullptr, nullptr); + page->page->display(gfx); + hasGraphics = bb_out->getHasGraphics(); + if (hasGraphics) { + rect->x1 = bb_out->getX1(); + rect->y1 = bb_out->getY1(); + rect->x2 = bb_out->getX2(); + rect->y2 = bb_out->getY2(); + } + + delete gfx; + delete bb_out; + return hasGraphics; +} + /** * poppler_page_get_text_layout: * @page: A #PopplerPage diff --git a/glib/poppler-page.h b/glib/poppler-page.h index f99f0920..0ffc50c6 100644 --- a/glib/poppler-page.h +++ b/glib/poppler-page.h @@ -132,6 +132,9 @@ POPPLER_PUBLIC void poppler_page_get_crop_box (PopplerPage *page, PopplerRectangle *rect); POPPLER_PUBLIC +gboolean poppler_page_get_bounding_box (PopplerPage *page, + PopplerRectangle *rect); +POPPLER_PUBLIC gboolean poppler_page_get_text_layout (PopplerPage *page, PopplerRectangle **rectangles, guint *n_rectangles); diff --git a/glib/reference/poppler-sections.txt b/glib/reference/poppler-sections.txt index 75bf3b09..e13b3c1c 100644 --- a/glib/reference/poppler-sections.txt +++ b/glib/reference/poppler-sections.txt @@ -53,6 +53,7 @@ poppler_page_free_image_mapping poppler_page_free_link_mapping poppler_page_free_text_attributes poppler_page_get_annot_mapping +poppler_page_get_bounding_box poppler_page_get_crop_box poppler_page_get_duration poppler_page_get_form_field_mapping diff --git a/glib/tests/CMakeLists.txt b/glib/tests/CMakeLists.txt new file mode 100644 index 00000000..ff776918 --- /dev/null +++ b/glib/tests/CMakeLists.txt @@ -0,0 +1,43 @@ +include_directories( + ${GTK3_INCLUDE_DIRS} +) + +macro(POPPLER_ADD_TESTCASE exe arg1) + add_test(${exe}-${arg1} ${EXE} ${EXECUTABLE_OUTPUT_PATH}/poppler-check-bb ${TESTDATADIR}/unittestcases/${arg1} ${ARGN}) +endmacro(POPPLER_ADD_TESTCASE) + +add_definitions(${GTK3_CFLAGS_OTHER}) +add_definitions(-DTESTDATADIR=\"${TESTDATADIR}\") + +set(poppler_check_text_SRCS + check_text.c +) +poppler_add_unittest(poppler-check-text BUILD_GTK_TESTS ${poppler_check_text_SRCS}) +target_link_libraries(poppler-check-text poppler-glib ${GTK3_LIBRARIES}) + +set(poppler_check_bb_SRCS + check_bb.c +) +poppler_add_test(poppler-check-bb BUILD_GTK_TESTS ${poppler_check_bb_SRCS}) +target_link_libraries(poppler-check-bb poppler-glib ${GTK3_LIBRARIES}) +poppler_add_testcase(poppler-check-bb shapes+attachments.pdf 42.5 42.5 557.5 557.5) +poppler_add_testcase(poppler-check-bb orientation.pdf 34 34 83.74 49 793 34 808 97.19 488.02 793 561 808 34 503.61 49 56) +poppler_add_testcase(poppler-check-bb xr01.pdf 148.71 127.85 308.11 704.57) +poppler_add_testcase(poppler-check-bb xr02.pdf 133.77 124.81 308.11 704.57 133.77 124.80 308.11 704.57) +poppler_add_testcase(poppler-check-bb russian.pdf 71.5 76.81 197.69 131.09) +poppler_add_testcase(poppler-check-bb vis_policy_test.pdf 90 77.93 312.01 265.13) +poppler_add_testcase(poppler-check-bb searchAcrossLines.pdf 107.15 105.23 523.85 691 85.04 94 538.59 762.19) +poppler_add_testcase(poppler-check-bb deseret.pdf 56.8 57.15 109.5 72.8) +poppler_add_testcase(poppler-check-bb fieldWithUtf16Names.pdf 56.65 56.65 264.55 83.05) +poppler_add_testcase(poppler-check-bb bug7063.pdf 56.8 57.46 244.29 118.79) +poppler_add_testcase(poppler-check-bb WithActualText.pdf 100 90.72 331.01 102.35) +poppler_add_testcase(poppler-check-bb Issue637.pdf 70.87 53 293 105.37) +poppler_add_testcase(poppler-check-bb truetype.pdf 17.5 17.5 577.5 225.62) +poppler_add_testcase(poppler-check-bb form_set_icon.pdf -0.5 -0.5 363.34 272.63) +poppler_add_testcase(poppler-check-bb imageretrieve+attachment.pdf 0 0 610.56 792) +poppler_add_testcase(poppler-check-bb checkbox_issue_159.pdf 2.84 14.17 553.18 840.87) +poppler_add_testcase(poppler-check-bb NestedLayers.pdf -1 191 613 793) +poppler_add_testcase(poppler-check-bb A6EmbeddedFiles.pdf 17.88 17.88 558.36 755.73) + +add_executable(pdfdrawbb pdfdrawbb.c) +target_link_libraries(pdfdrawbb poppler-glib) diff --git a/glib/tests/check_bb.c b/glib/tests/check_bb.c new file mode 100644 index 00000000..3170299a --- /dev/null +++ b/glib/tests/check_bb.c @@ -0,0 +1,92 @@ +/* + * testing program for the boundingbox function + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <math.h> + +#include <poppler.h> + +/* + * compare floating-point coordinates + */ +int equal(double a, double b) { + return fabs(a - b) < 0.01; +} + +/* + * main + */ +int main(int argc, char *argv[]) { + GFile *infile; + PopplerDocument *doc; + PopplerPage *page; + int npages, n; + gboolean hg; + PopplerRectangle bb, correct; + GError *err = NULL; + int argx; + + /* open file */ + + g_print("file: %s\n", argv[1]); + infile = g_file_new_for_path(argv[1]); + if (! infile) + exit(EXIT_FAILURE); + + doc = poppler_document_new_from_gfile(infile, NULL, NULL, &err); + if (doc == NULL) { + g_printerr("error opening pdf file: %s\n", err->message); + g_error_free(err); + exit(EXIT_FAILURE); + } + + /* pages */ + + npages = poppler_document_get_n_pages(doc); + if (npages < 1) { + g_printerr("no page in document\n"); + exit(EXIT_FAILURE); + } + + /* check the bounding box */ + + argx = 2; + for (n = 0; n < poppler_document_get_n_pages(doc); n++) { + g_print(" page: %d\n", n + 1); + + page = poppler_document_get_page(doc, n); + hg = poppler_page_get_bounding_box(page, &bb); + if (! hg) { + g_printerr("no graphics in page\n"); + exit(EXIT_FAILURE); + } + g_print(" bounding box: %g,%g - %g,%g\n", + bb.x1, bb.y1, bb.x2, bb.y2); + + if (argc - argx < 4) { + g_print("not enough arguments\n"); + exit(EXIT_FAILURE); + } + correct.x1 = atof(argv[argx++]); + correct.y1 = atof(argv[argx++]); + correct.x2 = atof(argv[argx++]); + correct.y2 = atof(argv[argx++]); + g_print(" correct: %g,%g - %g,%g\n", + correct.x1, correct.y1, correct.x2, correct.y2); + if (! equal(bb.x1, correct.x1) || + ! equal(bb.x2, correct.x2) || + ! equal(bb.y1, correct.y1) || + ! equal(bb.x2, correct.x2)) { + g_print("bounding box differs from expected\n"); + exit(EXIT_FAILURE); + } + + g_object_unref(page); + } + + return EXIT_SUCCESS; +} + diff --git a/glib/tests/check_text.c b/glib/tests/check_text.c new file mode 100644 index 00000000..cf5f2463 --- /dev/null +++ b/glib/tests/check_text.c @@ -0,0 +1,55 @@ +/* + * testing program for the get_text function + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include <poppler.h> + +/* + * main + */ +int main(int argc, char *argv[]) { + GFile *infile; + PopplerDocument *doc; + PopplerPage *page; + int npages, n; + char *text; + GError *err = NULL; + + /* open file */ + + infile = g_file_new_for_path + (TESTDATADIR "/unittestcases/WithActualText.pdf"); + if (! infile) + exit(EXIT_FAILURE); + + doc = poppler_document_new_from_gfile(infile, NULL, NULL, &err); + if (doc == NULL) { + g_printerr("error opening pdf file: %s\n", err->message); + g_error_free(err); + exit(EXIT_FAILURE); + } + + /* pages */ + + npages = poppler_document_get_n_pages(doc); + if (npages < 1) { + g_printerr("no page in document\n"); + exit(EXIT_FAILURE); + } + + /* check text */ + + n = 0; + page = poppler_document_get_page(doc, n); + text = poppler_page_get_text(page); + g_print("%s\n", text); + g_assert_cmpstr(text, ==, "The slow brown fox jumps over the black dog."); + g_object_unref(page); + + return EXIT_SUCCESS; +} + diff --git a/glib/tests/pdfdrawbb.c b/glib/tests/pdfdrawbb.c new file mode 100644 index 00000000..c136f861 --- /dev/null +++ b/glib/tests/pdfdrawbb.c @@ -0,0 +1,143 @@ +/* + * pdfdrawbb.c + * + * draw the bounding box of each page + */ + +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <string.h> + +#include <poppler.h> +#include <cairo.h> +#include <cairo-pdf.h> + +/* + * add suffix to a pdf filename + */ +char *pdfaddsuffix(char *infile, char *suffix) { + char *basename; + char *outfile; + char *pos; + + basename = g_path_get_basename(infile); + + outfile = malloc(strlen(infile) + strlen(suffix) + 10); + strcpy(outfile, basename); + g_free(basename); + + pos = strrchr(outfile, '.'); + if (pos != NULL && (! strcmp(pos, ".pdf") || ! strcmp(pos, ".PDF"))) + *pos = '\0'; + + strcat(outfile, "-"); + strcat(outfile, suffix); + strcat(outfile, ".pdf"); + return outfile; +} + +/* + * main + */ +int main(int argc, char *argv[]) { + int opt; + gboolean usage = FALSE; + char *infilename, *outfilename; + + GError *err = NULL; + GFile *infile; + PopplerDocument *doc; + PopplerPage *page; + int npages, n; + PopplerRectangle bb; + gboolean hg; + + gdouble width, height; + cairo_surface_t *surface; + cairo_t *cr; + + /* arguments */ + + while ((opt = getopt(argc, argv, "h")) != -1) + switch(opt) { + case 'h': + usage = TRUE; + break; + } + + if (! usage && argc - 1 < optind) { + g_print("input file name missing\n"); + usage = TRUE; + } + if (usage) { + g_print("usage:\n"); + g_print("\tpdfdrawbb"); + g_print("[-h] file.pdf\n"); + g_print("\t\t-h\t\tthis help\n"); + exit(EXIT_FAILURE); + } + infilename = argv[optind]; + if (! infilename) + exit(EXIT_FAILURE); + outfilename = pdfaddsuffix(argv[optind], "bb"); + + /* open file */ + + infile = g_file_new_for_path(infilename); + if (infile == NULL) + exit(EXIT_FAILURE); + + doc = poppler_document_new_from_gfile(infile, NULL, NULL, &err); + if (doc == NULL) { + g_printerr("error opening pdf file: %s\n", err->message); + g_error_free(err); + exit(EXIT_FAILURE); + } + + /* pages */ + + npages = poppler_document_get_n_pages(doc); + if (npages < 1) { + g_print("no page in document\n"); + exit(EXIT_FAILURE); + } + + /* copy to destination */ + + surface = cairo_pdf_surface_create(outfilename, width, height); + + g_print("infile: %s\n", infilename); + g_print("outfile: %s\n", outfilename); + + for (n = 0; n < npages; n++) { + g_print("page %d:\n", n); + page = poppler_document_get_page(doc, n); + poppler_page_get_size(page, &width, &height); + cairo_pdf_surface_set_size(surface, width, height); + + hg = poppler_page_get_bounding_box(page, &bb); + if (hg) + g_print("bounding box %g,%g - %g,%g", + bb.x1, bb.y1, bb.x2, bb.y2); + g_print("\n"); + + cr = cairo_create(surface); + poppler_page_render_for_printing(page, cr); + if (hg) { + cairo_set_source_rgb(cr, 0.6, 0.6, 1.0); + cairo_rectangle(cr, + bb.x1, bb.y1, bb.x2 - bb.x1, bb.y2 - bb.y1); + cairo_stroke(cr); + } + cairo_destroy(cr); + cairo_surface_show_page(surface); + + g_object_unref(page); + } + + cairo_surface_destroy(surface); + + return EXIT_SUCCESS; +} + diff --git a/poppler/BBoxOutputDev.cc b/poppler/BBoxOutputDev.cc new file mode 100644 index 00000000..e992d47b --- /dev/null +++ b/poppler/BBoxOutputDev.cc @@ -0,0 +1,251 @@ +/* + * boundingbox output device + */ + +#include <cmath> +#include <BBoxOutputDev.h> +#include <GfxFont.h> + +#define writingModeHorizontal 0 +#define writingModeVertical 1 + +BBoxOutputDev::BBoxOutputDev(const PDFRectangle *cropA) : + BBoxOutputDev(cropA, true, true, true) { +} + +BBoxOutputDev::BBoxOutputDev(const PDFRectangle *cropA, + bool textA, bool vectorA, bool rasterA) : + BBoxOutputDev(cropA, textA, vectorA, rasterA, true) { +} + +BBoxOutputDev::BBoxOutputDev(const PDFRectangle *cropA, + bool textA, bool vectorA, bool rasterA, bool lwidthA) { + hasGraphics = false; + crop = *cropA; + text = textA; + vector = vectorA; + raster = rasterA; + lwidth = lwidthA; +} + +double BBoxOutputDev::getX1() const { + return bb.x1; +} + +double BBoxOutputDev::getY1() const { + return bb.y1; +} + +double BBoxOutputDev::getX2() const { + return bb.x2; +} + +double BBoxOutputDev::getY2() const { + return bb.y2; +} + +double BBoxOutputDev::getHasGraphics() const { + return hasGraphics; +} + +void BBoxOutputDev::endPage() { + bb.clipTo(&crop); +} + +void BBoxOutputDev::stroke(GfxState *state) { + updatePath(&bb, state->getPath(), state); +} + +void BBoxOutputDev::fill(GfxState *state) { + updatePath(&bb, state->getPath(), state); +} + +void BBoxOutputDev::eoFill(GfxState *state) { + updatePath(&bb, state->getPath(), state); +} + +void BBoxOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, bool invert, + bool interpolate, + bool inlineImg) { + updateImage(&bb, state); +} + +void BBoxOutputDev::drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, bool interpolate, + const int *maskColors, bool inlineImg) { + updateImage(&bb, state); +} + +void BBoxOutputDev::drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, bool interpolate, + Stream *maskStr, int maskWidth, int maskHeight, + bool maskInvert, bool maskInterpolate) { + updateImage(&bb, state); +} + +void BBoxOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref, + Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + bool interpolate, + Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap, + bool maskInterpolate) { + updateImage(&bb, state); +} + +void BBoxOutputDev::drawChar(GfxState *state, + double x, double y, + double dx, double dy, + double originX, double originY, + CharCode code, int nBytes, + const Unicode *u, int uLen) { + GfxFont *font; + double leftent, rightent, ascent, descent; + const double *fm, *fb; + Matrix fmat; + double fontSize; + double fx, fy, nx, ny; + + if (! text) + return; + + font = state->getFont(); + if (! font) + return; + + if (code == (CharCode) 0x20) + return; + + fontSize = state->getFontSize(); + + if (font->getType() != fontType3) + fmat.init(1, 0, 0, 1, 0, 0); + else { + fm = font->getFontMatrix(); + fmat.init(fm[0], fm[1], fm[2], fm[3], fm[4], fm[5]); + } + + fb = font->getFontBBox(); + if (font->getWMode() == writingModeHorizontal) { + leftent = 0; + rightent = 0; + ascent = font->getAscent(); + descent = font->getDescent(); + } + else { + if (fb[0] == 0 && fb[1] == 0 && fb[2] == 0 && fb[3] == 0) { + leftent = -0.5; + rightent = 0.5; + } + else { + leftent = fb[1]; + rightent = fb[3]; + } + ascent = 0; + descent = 0; + } + if (font->getType() == fontType3) { + ascent *= 1000; + descent *= 1000; + } + + fmat.transform(leftent, descent, &fx, &fy); + state->textTransformDelta(fx, fy, &nx, &ny); + updatePoint(&bb, nx + x, ny + y, state); + + fmat.transform(rightent, ascent, &fx, &fy); + state->textTransformDelta(fx, fy, &nx, &ny); + updatePoint(&bb, nx + x, ny + y, state); + + fmat.transform(leftent * fontSize, descent * fontSize, &fx, &fy); + state->textTransformDelta(fx, fy, &nx, &ny); + updatePoint(&bb, nx + x + dx, ny + y + dy, state); + + fmat.transform(rightent * fontSize, ascent * fontSize, &fx, &fy); + state->textTransformDelta(fx, fy, &nx, &ny); + updatePoint(&bb, nx + x + dx, ny + y + dy, state); +} + +void BBoxOutputDev::clip(GfxState *state) { + updateClip(state); +} + +void BBoxOutputDev::eoClip(GfxState *state) { + updateClip(state); +} + +void BBoxOutputDev::clipToStrokePath(GfxState *state) { + updateClip(state); +} + +/* update the crop box with a new path */ +void BBoxOutputDev::updateClip(const GfxState *state) { + PDFRectangle box; + bool hg; + hg = hasGraphics; + hasGraphics = true; + updatePath(&box, state->getPath(), state); + hasGraphics = hg; + crop.clipTo(&box); +} + +/* update the bounding box with a new point */ +void BBoxOutputDev::updatePoint(PDFRectangle *bbA, + double x, double y, const GfxState *state) { + Matrix o = {1, 0, 0, 1, 0, 0}; + double tx, ty, fx, fy; + + o.scale(1, -1); + o.translate(0, -state->getPageHeight()); + + state->transform(x, y, &tx, &ty); + o.transform(tx, ty, &fx, &fy); + + if (! hasGraphics || bbA->x1 > fx) + bbA->x1 = fx; + if (! hasGraphics || bbA->y1 > fy) + bbA->y1 = fy; + if (! hasGraphics || bbA->x2 < fx) + bbA->x2 = fx; + if (! hasGraphics || bbA->y2 < fy) + bbA->y2 = fy; + hasGraphics = true; +} + +/* update the bounding box with a new path */ +void BBoxOutputDev::updatePath(PDFRectangle *bbA, + const GfxPath *path, const GfxState *state) { + int i, j; + const GfxSubpath *subpath; + double w; + if (! vector) + return; + w = lwidth ? state->getLineWidth() : 0; + for (i = 0; i < path->getNumSubpaths(); i++) { + subpath = path->getSubpath(i); + for (j = 0; j < subpath->getNumPoints(); j++) { + updatePoint(bbA, + subpath->getX(j) - w / 2, + subpath->getY(j) - w / 2, + state); + updatePoint(bbA, + subpath->getX(j) + w / 2, + subpath->getY(j) + w / 2, + state); + } + } +} + +/* update the bounding box with a new image */ +void BBoxOutputDev::updateImage(PDFRectangle *bbA, const GfxState *state) { + if (! raster) + return; + updatePoint(bbA, 0, 1, state); + updatePoint(bbA, 1, 0, state); +} + diff --git a/poppler/BBoxOutputDev.h b/poppler/BBoxOutputDev.h new file mode 100644 index 00000000..7b28a94e --- /dev/null +++ b/poppler/BBoxOutputDev.h @@ -0,0 +1,73 @@ +#include <PDFDoc.h> +#include <GfxState.h> +#include <OutputDev.h> + +class BBoxOutputDev: public OutputDev { +public: + bool upsideDown() override { return false; } + bool useDrawChar() override { return true; } + bool interpretType3Chars() override { return false; } + + BBoxOutputDev(const PDFRectangle *cropA); + BBoxOutputDev(const PDFRectangle *cropA, + bool text, bool vector, bool raster); + BBoxOutputDev(const PDFRectangle *cropA, + bool text, bool vector, bool raster, bool lwidth); + void endPage() override; + void stroke(GfxState *state) override; + void fill(GfxState *state) override; + void eoFill(GfxState *state) override; + void drawChar(GfxState *state, double x, double y, + double dx, double dy, + double originX, double originY, + CharCode code, int nBytes, + const Unicode *u, int uLen) override; + void drawImageMask(GfxState *state, Object *ref, Stream *str, + int width, int height, bool invert, + bool interpolate, + bool inlineImg) override; + void drawImage(GfxState *state, Object *ref, Stream *str, + int width, int height, GfxImageColorMap *colorMap, + bool interpolate, const int *maskColors, + bool inlineImg) override; + void drawMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, bool interpolate, + Stream *maskStr, int maskWidth, int maskHeight, + bool maskInvert, bool maskInterpolate) override; + void drawSoftMaskedImage(GfxState *state, Object *ref, Stream *str, + int width, int height, + GfxImageColorMap *colorMap, + bool interpolate, + Stream *maskStr, + int maskWidth, int maskHeight, + GfxImageColorMap *maskColorMap, + bool maskInterpolate) override; + void clip(GfxState *state) override; + void eoClip(GfxState *state) override; + void clipToStrokePath(GfxState *state) override; + + double getX1() const; + double getY1() const; + double getX2() const; + double getY2() const; + double getHasGraphics() const; + +private: + PDFRectangle bb; + PDFRectangle crop; + bool hasGraphics; + + bool text; + bool vector; + bool raster; + bool lwidth; + + void updatePoint(PDFRectangle *bbA, + double x, double y, const GfxState *state); + void updatePath(PDFRectangle *bbA, + const GfxPath *path, const GfxState *state); + void updateImage(PDFRectangle *bbA, const GfxState *state); + void updateClip(const GfxState *state); +}; + _______________________________________________ poppler mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/poppler
