mirror of
https://github.com/pdf2htmlEX/pdf2htmlEX.git
synced 2024-12-22 04:50:09 +00:00
Handle clips during processing of covered text.
This commit is contained in:
parent
bd3f165ae2
commit
1d95b73eee
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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();
|
||||
|
@ -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)
|
||||
|
@ -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); };
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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__
|
||||
|
Loading…
Reference in New Issue
Block a user