Commit 0da16537 authored by Carlos Garcia Campos's avatar Carlos Garcia Campos

Refactor actual text code adding a new ActualText class

It's used by both Text and Cairo ouput devices avoiding duplicated code
in such classes.
parent 0f8ab301
......@@ -138,7 +138,7 @@ CairoOutputDev::CairoOutputDev() {
knockoutCount = 0;
text = NULL;
actualTextBMCLevel = 0;
actualText = NULL;
}
CairoOutputDev::~CairoOutputDev() {
......@@ -157,7 +157,9 @@ CairoOutputDev::~CairoOutputDev() {
if (shape)
cairo_pattern_destroy (shape);
if (text)
text->decRefCnt();
text->decRefCnt();
if (actualText)
delete actualText;
}
void CairoOutputDev::setCairo(cairo_t *cairo)
......@@ -185,11 +187,15 @@ void CairoOutputDev::setTextPage(TextPage *text)
{
if (this->text)
this->text->decRefCnt();
if (actualText)
delete actualText;
if (text) {
this->text = text;
this->text->incRefCnt();
actualText = new ActualText(text);
} else {
this->text = NULL;
actualText = NULL;
}
}
......@@ -608,28 +614,7 @@ void CairoOutputDev::drawChar(GfxState *state, double x, double y,
if (!text)
return;
if (actualTextBMCLevel == 0) {
text->addChar(state, x, y, dx, dy, code, nBytes, u, uLen);
} else {
// Inside ActualText span.
if (newActualTextSpan) {
actualText_x = x;
actualText_y = y;
actualText_dx = dx;
actualText_dy = dy;
newActualTextSpan = gFalse;
} else {
if (x < actualText_x)
actualText_x = x;
if (y < actualText_y)
actualText_y = y;
if (x + dx > actualText_x + actualText_dx)
actualText_dx = x + dx - actualText_x;
if (y + dy > actualText_y + actualText_dy)
actualText_dy = y + dy - actualText_y;
}
}
actualText->addChar (state, x, y, dx, dy, code, nBytes, u, uLen);
}
void CairoOutputDev::endString(GfxState *state)
......@@ -774,81 +759,14 @@ void CairoOutputDev::endTextObject(GfxState *state) {
void CairoOutputDev::beginMarkedContent(char *name, Dict *properties)
{
Object obj;
if (!text)
return;
if (actualTextBMCLevel > 0) {
// Already inside a ActualText span.
actualTextBMCLevel++;
return;
}
if (properties->lookup("ActualText", &obj)) {
if (obj.isString()) {
actualText = obj.getString();
actualTextBMCLevel = 1;
newActualTextSpan = gTrue;
}
}
if (text)
actualText->beginMC(properties);
}
void CairoOutputDev::endMarkedContent(GfxState *state)
{
char *uniString = NULL;
Unicode *uni;
int length, i;
if (!text)
return;
if (actualTextBMCLevel > 0) {
actualTextBMCLevel--;
if (actualTextBMCLevel == 0) {
// ActualText span closed. Output the span text and the
// extents of all the glyphs inside the span
if (newActualTextSpan) {
// No content inside span.
actualText_x = state->getCurX();
actualText_y = state->getCurY();
actualText_dx = 0;
actualText_dy = 0;
}
if (!actualText->hasUnicodeMarker()) {
if (actualText->getLength() > 0) {
//non-unicode string -- assume pdfDocEncoding and
//try to convert to UTF16BE
uniString = pdfDocEncodingToUTF16(actualText, &length);
} else {
length = 0;
}
} else {
uniString = actualText->getCString();
length = actualText->getLength();
}
if (length < 3)
length = 0;
else
length = length/2 - 1;
uni = new Unicode[length];
for (i = 0 ; i < length; i++)
uni[i] = (uniString[2 + i*2]<<8) + uniString[2 + i*2+1];
text->addChar(state,
actualText_x, actualText_y,
actualText_dx, actualText_dy,
0, 1, uni, length);
delete [] uni;
if (!actualText->hasUnicodeMarker())
delete [] uniString;
delete actualText;
}
}
if (text)
actualText->endMC(state);
}
static inline int splashRound(SplashCoord x) {
......
......@@ -258,12 +258,7 @@ protected:
GBool prescaleImages;
TextPage *text; // text for the current page
int actualTextBMCLevel; // > 0 when inside ActualText span. Incremented
// for each nested BMC inside the span.
GooString *actualText; // replacement text for the span
GBool newActualTextSpan; // true at start of span. used to init the extent
double actualText_x, actualText_y; // extent of the text inside the span
double actualText_dx, actualText_dy;
ActualText *actualText;
cairo_pattern_t *group;
cairo_pattern_t *shape;
......
......@@ -4493,6 +4493,118 @@ TextWordList *TextPage::makeWordList(GBool physLayout) {
}
#endif
//------------------------------------------------------------------------
// ActualText
//------------------------------------------------------------------------
ActualText::ActualText(TextPage *out) {
out->incRefCnt();
text = out;
actualText = NULL;
actualTextBMCLevel = 0;
}
ActualText::~ActualText() {
if (actualText)
delete actualText;
text->decRefCnt();
}
void ActualText::addChar(GfxState *state, double x, double y,
double dx, double dy,
CharCode c, int nBytes, Unicode *u, int uLen) {
if (actualTextBMCLevel == 0) {
text->addChar(state, x, y, dx, dy, c, nBytes, u, uLen);
} else {
// Inside ActualText span.
if (newActualTextSpan) {
actualText_x = x;
actualText_y = y;
actualText_dx = dx;
actualText_dy = dy;
newActualTextSpan = gFalse;
} else {
if (x < actualText_x)
actualText_x = x;
if (y < actualText_y)
actualText_y = y;
if (x + dx > actualText_x + actualText_dx)
actualText_dx = x + dx - actualText_x;
if (y + dy > actualText_y + actualText_dy)
actualText_dy = y + dy - actualText_y;
}
}
}
void ActualText::beginMC(Dict *properties) {
if (actualTextBMCLevel > 0) {
// Already inside a ActualText span.
actualTextBMCLevel++;
return;
}
Object obj;
if (properties->lookup("ActualText", &obj)) {
if (obj.isString()) {
actualText = obj.getString();
actualTextBMCLevel = 1;
newActualTextSpan = gTrue;
}
}
}
void ActualText::endMC(GfxState *state) {
char *uniString = NULL;
Unicode *uni;
int length, i;
if (actualTextBMCLevel > 0) {
actualTextBMCLevel--;
if (actualTextBMCLevel == 0) {
// ActualText span closed. Output the span text and the
// extents of all the glyphs inside the span
if (newActualTextSpan) {
// No content inside span.
actualText_x = state->getCurX();
actualText_y = state->getCurY();
actualText_dx = 0;
actualText_dy = 0;
}
if (!actualText->hasUnicodeMarker()) {
if (actualText->getLength() > 0) {
//non-unicode string -- assume pdfDocEncoding and
//try to convert to UTF16BE
uniString = pdfDocEncodingToUTF16(actualText, &length);
} else {
length = 0;
}
} else {
uniString = actualText->getCString();
length = actualText->getLength();
}
if (length < 3)
length = 0;
else
length = length/2 - 1;
uni = new Unicode[length];
for (i = 0 ; i < length; i++)
uni[i] = (uniString[2 + i*2]<<8) + uniString[2 + i*2+1];
text->addChar(state,
actualText_x, actualText_y,
actualText_dx, actualText_dy,
0, 1, uni, length);
delete [] uni;
if (!actualText->hasUnicodeMarker())
delete [] uniString;
delete actualText;
}
}
}
//------------------------------------------------------------------------
// TextOutputDev
//------------------------------------------------------------------------
......@@ -4532,7 +4644,7 @@ TextOutputDev::TextOutputDev(char *fileName, GBool physLayoutA,
// set up text object
text = new TextPage(rawOrderA);
actualTextBMCLevel = 0;
actualText = new ActualText(text);
}
TextOutputDev::TextOutputDev(TextOutputFunc func, void *stream,
......@@ -4544,8 +4656,8 @@ TextOutputDev::TextOutputDev(TextOutputFunc func, void *stream,
rawOrder = rawOrderA;
doHTML = gFalse;
text = new TextPage(rawOrderA);
actualText = new ActualText(text);
ok = gTrue;
actualTextBMCLevel = 0;
}
TextOutputDev::~TextOutputDev() {
......@@ -4558,6 +4670,7 @@ TextOutputDev::~TextOutputDev() {
if (text) {
text->decRefCnt();
}
delete actualText;
}
void TextOutputDev::startPage(int pageNum, GfxState *state) {
......@@ -4586,100 +4699,17 @@ void TextOutputDev::drawChar(GfxState *state, double x, double y,
double dx, double dy,
double originX, double originY,
CharCode c, int nBytes, Unicode *u, int uLen) {
if (actualTextBMCLevel == 0) {
text->addChar(state, x, y, dx, dy, c, nBytes, u, uLen);
} else {
// Inside ActualText span.
if (newActualTextSpan) {
actualText_x = x;
actualText_y = y;
actualText_dx = dx;
actualText_dy = dy;
newActualTextSpan = gFalse;
} else {
if (x < actualText_x)
actualText_x = x;
if (y < actualText_y)
actualText_y = y;
if (x + dx > actualText_x + actualText_dx)
actualText_dx = x + dx - actualText_x;
if (y + dy > actualText_y + actualText_dy)
actualText_dy = y + dy - actualText_y;
}
}
actualText->addChar(state, x, y, dx, dy, c, nBytes, u, uLen);
}
void TextOutputDev::beginMarkedContent(char *name, Dict *properties)
{
Object obj;
if (actualTextBMCLevel > 0) {
// Already inside a ActualText span.
actualTextBMCLevel++;
return;
}
if (properties->lookup("ActualText", &obj)) {
if (obj.isString()) {
actualText = obj.getString();
actualTextBMCLevel = 1;
newActualTextSpan = gTrue;
}
}
actualText->beginMC(properties);
}
void TextOutputDev::endMarkedContent(GfxState *state)
{
char *uniString = NULL;
Unicode *uni;
int length, i;
if (actualTextBMCLevel > 0) {
actualTextBMCLevel--;
if (actualTextBMCLevel == 0) {
// ActualText span closed. Output the span text and the
// extents of all the glyphs inside the span
if (newActualTextSpan) {
// No content inside span.
actualText_x = state->getCurX();
actualText_y = state->getCurY();
actualText_dx = 0;
actualText_dy = 0;
}
if (!actualText->hasUnicodeMarker()) {
if (actualText->getLength() > 0) {
//non-unicode string -- assume pdfDocEncoding and
//try to convert to UTF16BE
uniString = pdfDocEncodingToUTF16(actualText, &length);
} else {
length = 0;
}
} else {
uniString = actualText->getCString();
length = actualText->getLength();
}
if (length < 3)
length = 0;
else
length = length/2 - 1;
uni = new Unicode[length];
for (i = 0 ; i < length; i++)
uni[i] = (uniString[2 + i*2]<<8) + uniString[2 + i*2+1];
text->addChar(state,
actualText_x, actualText_y,
actualText_dx, actualText_dy,
0, 1, uni, length);
delete [] uni;
if (!actualText->hasUnicodeMarker())
delete [] uniString;
delete actualText;
}
}
actualText->endMC(state);
}
void TextOutputDev::stroke(GfxState *state) {
......
......@@ -613,6 +613,33 @@ private:
friend class TextSelectionDumper;
};
//------------------------------------------------------------------------
// ActualText
//------------------------------------------------------------------------
class ActualText {
public:
// Create an ActualText
ActualText(TextPage *out);
~ActualText();
void addChar(GfxState *state, double x, double y,
double dx, double dy,
CharCode c, int nBytes, Unicode *u, int uLen);
void beginMC(Dict *properties);
void endMC(GfxState *state);
private:
TextPage *text;
int actualTextBMCLevel; // > 0 when inside ActualText span. Incremented
// for each nested BMC inside the span.
GooString *actualText; // replacement text for the span
GBool newActualTextSpan; // true at start of span. used to init the extent
double actualText_x, actualText_y; // extent of the text inside the span
double actualText_dx, actualText_dy;
};
//------------------------------------------------------------------------
// TextOutputDev
//------------------------------------------------------------------------
......@@ -755,12 +782,7 @@ private:
GBool doHTML; // extra processing for HTML conversion
GBool ok; // set up ok?
int actualTextBMCLevel; // > 0 when inside ActualText span. Incremented
// for each nested BMC inside the span.
GooString *actualText; // replacement text for the span
GBool newActualTextSpan; // true at start of span. used to init the extent
double actualText_x, actualText_y; // extent of the text inside the span
double actualText_dx, actualText_dy;
ActualText *actualText;
};
#endif
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment