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:
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;
|
||||
|
@ -150,23 +150,57 @@ 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
|
||||
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];
|
||||
// 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);
|
||||
// TODO intersect
|
||||
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