1
0
mirror of https://github.com/pdf2htmlEX/pdf2htmlEX.git synced 2024-12-22 13:00:08 +00:00

Handle clips during processing of covered text.

This commit is contained in:
Duan Yao 2014-06-15 16:42:34 +08:00
parent bd3f165ae2
commit 1d95b73eee
8 changed files with 100 additions and 30 deletions

View File

@ -30,11 +30,18 @@ void CoveredTextHandler::reset()
void CoveredTextHandler::add_char_bbox(double * bbox)
{
for (int i = 0; i < 4; i++)
char_bboxes.push_back(bbox[i]);
char_bboxes.insert(char_bboxes.end(), bbox, bbox + 4);
chars_covered.push_back(false);
}
void CoveredTextHandler::add_char_bbox_clipped(double * bbox, bool patially)
{
char_bboxes.insert(char_bboxes.end(), bbox, bbox + 4);
chars_covered.push_back(true);
if (patially)
add_non_char_bbox(bbox, chars_covered.size() - 1);
}
void CoveredTextHandler::add_non_char_bbox(double * bbox, int index)
{
if (index < 0)

View File

@ -32,6 +32,8 @@ public:
*/
void add_char_bbox(double * bbox);
void add_char_bbox_clipped(double * bbox, bool patially);
/**
* Add a drawn non-char graphics' bounding box.
* If it intersects any previously drawn char's bbox, the char is marked as covered
@ -51,7 +53,6 @@ public:
const std::vector<bool> & get_chars_covered() { return chars_covered; }
private:
//covered text test
std::vector<bool> chars_covered;
// x00, y00, x01, y01; x10, y10, x11, y11;...
std::vector<double> char_bboxes;

View File

@ -53,15 +53,15 @@ void DrawingTracer::set_ctm(GfxState *state)
matrix.yy = ctm[3];
matrix.x0 = ctm[4];
matrix.y0 = ctm[5];
cairo_set_matrix (cairo, &matrix);
cairo_set_matrix(cairo, &matrix);
}
void DrawingTracer::clip(GfxState * state, bool even_odd)
{
if (!param.process_covered_text)
return;
do_path (state, state->getPath());
cairo_set_fill_rule (cairo, even_odd? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
do_path(state, state->getPath());
cairo_set_fill_rule(cairo, even_odd? CAIRO_FILL_RULE_EVEN_ODD : CAIRO_FILL_RULE_WINDING);
cairo_clip (cairo);
}
@ -91,13 +91,13 @@ void DrawingTracer::do_path(GfxState * state, GfxPath * path)
GfxSubpath *subpath;
int i, j;
double x, y;
cairo_new_path (cairo);
cairo_new_path(cairo);
for (i = 0; i < path->getNumSubpaths(); ++i) {
subpath = path->getSubpath(i);
if (subpath->getNumPoints() > 0) {
x = subpath->getX(0);
y = subpath->getY(0);
cairo_move_to (cairo, x, y);
cairo_move_to(cairo, x, y);
j = 1;
while (j < subpath->getNumPoints()) {
if (subpath->getCurve(j)) {
@ -111,7 +111,7 @@ void DrawingTracer::do_path(GfxState * state, GfxPath * path)
} else {
x = subpath->getX(j);
y = subpath->getY(j);
cairo_line_to (cairo, x, y);
cairo_line_to(cairo, x, y);
++j;
}
}
@ -150,22 +150,56 @@ void DrawingTracer::fill(GfxState * state, bool even_odd)
void DrawingTracer::draw_non_char_bbox(GfxState * state, double * bbox)
{
double cbox[4], result[4];
double cbox[4];
cairo_clip_extents(cairo, cbox, cbox + 1, cbox + 2, cbox + 3);
// TODO intersect
tm_transform_bbox(state->getCTM(), bbox);
if (on_non_char_drawn)
on_non_char_drawn(bbox);
if(bbox_intersect(cbox, bbox, bbox))
{
tm_transform_bbox(state->getCTM(), bbox);
if (on_non_char_drawn)
on_non_char_drawn(bbox);
}
}
void DrawingTracer::draw_char_bbox(GfxState * state, double * bbox)
{
double cbox[4], result[4];
cairo_clip_extents(cairo, cbox, cbox + 1, cbox + 2, cbox + 3);
// TODO intersect
tm_transform_bbox(state->getCTM(), bbox);
if (on_char_drawn)
on_char_drawn(bbox);
// Note: even if 4 corner of the char are all in the clip area,
// it still could be partially clipped.
// TODO better solution?
int pt_in = 0;
if (cairo_in_clip(cairo, bbox[0], bbox[1]))
++pt_in;
if (cairo_in_clip(cairo, bbox[2], bbox[3]))
++pt_in;
if (cairo_in_clip(cairo, bbox[2], bbox[1]))
++pt_in;
if (cairo_in_clip(cairo, bbox[0], bbox[3]))
++pt_in;
if (pt_in == 0)
{
if(on_char_clipped)
on_char_clipped(bbox, false);
}
else
{
if (pt_in < 4)
{
double cbox[4];
cairo_clip_extents(cairo, cbox, cbox + 1, cbox + 2, cbox + 3);
bbox_intersect(cbox, bbox, bbox);
}
tm_transform_bbox(state->getCTM(), bbox);
if (pt_in < 4)
{
if(on_char_clipped)
on_char_clipped(bbox, true);
}
else
{
if (on_char_drawn)
on_char_drawn(bbox);
}
}
}
void DrawingTracer::draw_image(GfxState *state)

View File

@ -25,9 +25,12 @@ public:
* The callback to receive drawn event.
* bbox in device space.
*/
// a non-char graphics is drawn
std::function<void(double * bbox)> on_non_char_drawn;
// a char is drawn in the clip area
std::function<void(double * bbox)> on_char_drawn;
std::function<void(double * bbox)> on_char_clipped;
// a char is drawn out of/partially in the clip area
std::function<void(double * bbox, bool patially)> on_char_clipped;
DrawingTracer(const Param & param);
virtual ~DrawingTracer();

View File

@ -32,7 +32,8 @@ using std::ostream;
void HTMLRenderer::restoreState(GfxState * state)
{
updateAll(state); tracer.restore();
updateAll(state);
tracer.restore();
}
void HTMLRenderer::saveState(GfxState *state)

View File

@ -82,7 +82,7 @@ HTMLRenderer::HTMLRenderer(const Param & param)
tracer.on_char_drawn =
[this](double * box) { covered_text_handler.add_char_bbox(box); };
tracer.on_char_clipped =
[this](double * box) { covered_text_handler.add_char_bbox(box); }; //TODO
[this](double * box, bool partial) { covered_text_handler.add_char_bbox_clipped(box, partial); };
tracer.on_non_char_drawn =
[this](double * box) { covered_text_handler.add_non_char_bbox(box); };
}

View File

@ -60,12 +60,30 @@ void tm_transform_bbox(const double * tm, double * bbox)
}
}
bool bbox_intersect(double * bbox1, double * bbox2)
bool bbox_intersect(const double * bbox1, const double * bbox2, double * result)
{
return min(bbox1[0], bbox1[2]) < max(bbox2[0], bbox2[2])
&& max(bbox1[0], bbox1[2]) > min(bbox2[0], bbox2[2])
&& min(bbox1[1], bbox1[3]) < max(bbox2[1], bbox2[3])
&& max(bbox1[1], bbox1[3]) > min(bbox2[1], bbox2[3]);
double x0, y0, x1, y1;
x0 = max(min(bbox1[0], bbox1[2]), min(bbox2[0], bbox2[2]));
x1 = min(max(bbox1[0], bbox1[2]), max(bbox2[0], bbox2[2]));
if (x0 >= x1)
return false;
y0 = max(min(bbox1[1], bbox1[3]), min(bbox2[1], bbox2[3]));
y1 = min(max(bbox1[1], bbox1[3]), max(bbox2[1], bbox2[3]));
if (y0 >= y1)
return false;
if (result)
{
result[0] = x0;
result[1] = y0;
result[2] = x1;
result[3] = y1;
}
return true;
}
} //namespace pdf2htmlEX

View File

@ -39,8 +39,14 @@ static inline double hypot(double x, double y) { return std::sqrt(x*x+y*y); }
void tm_transform(const double * tm, double & x, double & y, bool is_delta = false);
void tm_multiply(double * tm_left, const double * tm_right);
void tm_transform_bbox(const double * tm, double * bbox);
bool bbox_intersect(double * bbox1, double * bbox2);
/**
* Calculate the intersection of 2 boxes.
* If they are intersecting, store the result to result (if not null) and return true.
* Otherwise return false, and result is not touched.
* Param result can be same as one of bbox1 and bbox2.
* Data in boxes are expected in the order of (x0, y0, x1, y1).
*/
bool bbox_intersect(const double * bbox1, const double * bbox2, double * result = nullptr);
} //namespace pdf2htmlEX
#endif //MATH_H__