Stamp Rotate

This commit is contained in:
Svetlana Kulikova
2024-10-18 10:03:11 +03:00
parent 8cadb329b9
commit 1eba4aefa8
7 changed files with 318 additions and 9 deletions

View File

@ -1281,9 +1281,14 @@ CFile.prototype["getAnnotationsInfo"] = function(pageIndex)
if (flags & (1 << 26)) if (flags & (1 << 26))
rec["Desc"] = reader.readString(); rec["Desc"] = reader.readString();
} }
// Stamp
else if (rec["Type"] == 12) else if (rec["Type"] == 12)
{ {
rec["Icon"] = reader.readString(); rec["Icon"] = reader.readString();
rec["Rotate"] = reader.readInt();
rec["InRect"] = [];
for (let i = 0; i < 8; ++i)
rec["InRect"].push(reader.readDouble2());
} }
res.push(rec); res.push(rec);
} }

View File

@ -998,6 +998,9 @@ int main(int argc, char* argv[])
nWidth = READ_INT(pInfo + i * 16 + 12); nWidth = READ_INT(pInfo + i * 16 + 12);
nHeight = READ_INT(pInfo + i * 16 + 16); nHeight = READ_INT(pInfo + i * 16 + 16);
//nWidth *= 3;
//nHeight *= 3;
BYTE* res = NULL; BYTE* res = NULL;
res = GetPixmap(pGrFile, i, nWidth, nHeight, 0xFFFFFF); res = GetPixmap(pGrFile, i, nWidth, nHeight, 0xFFFFFF);
@ -1791,8 +1794,44 @@ int main(int argc, char* argv[])
{ {
nPathLength = READ_INT(pAnnots + i); nPathLength = READ_INT(pAnnots + i);
i += 4; i += 4;
std::cout << "Icon " << std::string((char*)(pAnnots + i), nPathLength); std::cout << "Icon " << std::string((char*)(pAnnots + i), nPathLength) << ", ";
i += nPathLength; i += nPathLength;
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "Rotate " << nPathLength << ", ";
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "X1 " << (double)nPathLength / 10000.0 << ", ";
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "Y1 " << (double)nPathLength / 10000.0 << ", ";
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "X2 " << (double)nPathLength / 10000.0 << ", ";
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "Y2 " << (double)nPathLength / 10000.0 << ", ";
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "X3 " << (double)nPathLength / 10000.0 << ", ";
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "Y3 " << (double)nPathLength / 10000.0 << ", ";
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "X4 " << (double)nPathLength / 10000.0 << ", ";
nPathLength = READ_INT(pAnnots + i);
i += 4;
std::cout << "Y4 " << (double)nPathLength / 10000.0 << ", ";
} }
std::cout << std::endl << std::endl; std::cout << std::endl << std::endl;

View File

@ -2318,6 +2318,106 @@ CAnnotStamp::CAnnotStamp(PDFDoc* pdfDoc, Object* oAnnotRef, int nPageIndex) : CA
} }
oObj.free(); oObj.free();
m_nRotate = 0;
if (oAnnot.dictLookup("Rotate", &oObj)->isInt())
m_nRotate = oObj.getInt();
oObj.free();
double m[6] = { 1, 0, 0, 1, 0, 0 }, bbox[4] = { 0, 0, 0, 0 };
Object oAP, oObj2;
if (oAnnot.dictLookup("AP", &oAP)->isDict() && oAP.dictLookup("N", &oObj2)->isStream())
{
Object oObj1;
if (oObj2.streamGetDict()->lookup("BBox", &oObj)->isArray() && oObj.arrayGetLength() == 4)
{
for (int i = 0; i < 4; ++i)
{
oObj.arrayGet(i, &oObj1);
bbox[i] = oObj1.isNum() ? oObj1.getNum() : 0;
oObj1.free();
}
}
oObj.free();
if (oObj2.streamGetDict()->lookup("Matrix", &oObj)->isArray() && oObj.arrayGetLength() == 6)
{
for (int i = 0; i < 6; ++i)
{
oObj.arrayGet(i, &oObj1);
m[i] = oObj1.getNum();
oObj1.free();
}
}
}
oAP.free(); oObj2.free(); oObj.free();
double formXMin, formYMin, formXMax, formYMax, x, y, sx, sy;
x = bbox[0] * m[0] + bbox[1] * m[2] + m[4];
y = bbox[0] * m[1] + bbox[1] * m[3] + m[5];
formXMin = formXMax = x;
formYMin = formYMax = y;
x = bbox[0] * m[0] + bbox[3] * m[2] + m[4];
y = bbox[0] * m[1] + bbox[3] * m[3] + m[5];
if (x < formXMin)
formXMin = x;
else if (x > formXMax)
formXMax = x;
if (y < formYMin)
formYMin = y;
else if (y > formYMax)
formYMax = y;
x = bbox[2] * m[0] + bbox[1] * m[2] + m[4];
y = bbox[2] * m[1] + bbox[1] * m[3] + m[5];
if (x < formXMin)
formXMin = x;
else if (x > formXMax)
formXMax = x;
if (y < formYMin)
formYMin = y;
else if (y > formYMax)
formYMax = y;
x = bbox[2] * m[0] + bbox[3] * m[2] + m[4];
y = bbox[2] * m[1] + bbox[3] * m[3] + m[5];
if (x < formXMin)
formXMin = x;
else if (x > formXMax)
formXMax = x;
if (y < formYMin)
formYMin = y;
else if (y > formYMax)
formYMax = y;
if (formXMin == formXMax)
sx = 1;
else
sx = (m_pRect[2] - m_pRect[0]) / (formXMax - formXMin);
if (formYMin == formYMax)
sy = 1;
else
sy = (m_pRect[3] - m_pRect[1]) / (formYMax - formYMin);
double tx = -formXMin * sx + m_pRect[0];
double ty = -formYMin * sy + m_pRect[1];
m[0] *= sx;
m[1] *= sy;
m[2] *= sx;
m[3] *= sy;
m[4] = m[4] * sx + tx;
m[5] = m[5] * sy + ty;
m_dX1 = bbox[0] * m[0] + bbox[1] * m[2] + m[4];
m_dY1 = bbox[0] * m[1] + bbox[1] * m[3] + m[5];
m_dX2 = bbox[0] * m[0] + bbox[3] * m[2] + m[4];
m_dY2 = bbox[0] * m[1] + bbox[3] * m[3] + m[5];
m_dX3 = bbox[2] * m[0] + bbox[3] * m[2] + m[4];
m_dY3 = bbox[2] * m[1] + bbox[3] * m[3] + m[5];
m_dX4 = bbox[2] * m[0] + bbox[1] * m[2] + m[4];
m_dY4 = bbox[2] * m[1] + bbox[1] * m[3] + m[5];
oAnnot.free(); oAnnot.free();
} }
@ -2354,6 +2454,16 @@ CAnnots::CAnnots(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontLi
oField.free(); oFieldRef.free(); oField.free(); oFieldRef.free();
continue; continue;
} }
if (pField->getPageNum() < 1)
{
oField.free(); oFieldRef.free();
std::vector<int>::iterator it = std::find(m_arrCO.begin(), m_arrCO.end(), oFieldRef.getRefNum());
if (it != m_arrCO.end())
m_arrCO.erase(it);
continue;
}
// Родители // Родители
Object oParentRefObj; Object oParentRefObj;
if (oField.dictLookupNF("Parent", &oParentRefObj)->isRef()) if (oField.dictLookupNF("Parent", &oParentRefObj)->isRef())
@ -3127,18 +3237,19 @@ CAnnotAP::CAnnotAP(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFont
m_pRendererOut = NULL; m_pRendererOut = NULL;
m_pRenderer = NULL; m_pRenderer = NULL;
Object oAnnot, oAP; Object oAnnot, oAP, oSubtype;
XRef* xref = pdfDoc->getXRef(); XRef* xref = pdfDoc->getXRef();
oAnnotRef->fetch(xref, &oAnnot); oAnnotRef->fetch(xref, &oAnnot);
bIsStamp = oAnnot.dictLookup("Subtype", &oSubtype)->isName("Stamp");
if (oAnnot.dictLookup("AP", &oAP)->isDict()) if (oAnnot.dictLookup("AP", &oAP)->isDict())
{ {
m_unRefNum = oAnnotRef->getRefNum(); m_unRefNum = oAnnotRef->getRefNum();
Init(&oAnnot); double dScale = Init(&oAnnot);
Init(pdfDoc, pFontManager, pFontList, nRasterW, nRasterH, nBackgroundColor, nPageIndex); Init(pdfDoc, pFontManager, pFontList, nRasterW * dScale, nRasterH * dScale, nBackgroundColor, nPageIndex);
Draw(pdfDoc, &oAP, nRasterH, nBackgroundColor, oAnnotRef, sView); Draw(pdfDoc, &oAP, nRasterH * dScale, nBackgroundColor, oAnnotRef, sView);
} }
oAP.free(); oAnnot.free(); oAP.free(); oAnnot.free(); oSubtype.free();
Clear(); Clear();
} }
@ -3229,8 +3340,9 @@ void CAnnotAP::Init(AcroFormField* pField)
// Координаты - BBox // Координаты - BBox
pField->getBBox(&m_dx1, &m_dy1, &m_dx2, &m_dy2); pField->getBBox(&m_dx1, &m_dy1, &m_dx2, &m_dy2);
} }
void CAnnotAP::Init(Object* oAnnot) double CAnnotAP::Init(Object* oAnnot)
{ {
double dScale = 1.0;
Object oObj, oObj2; Object oObj, oObj2;
if (oAnnot->dictLookup("Rect", &oObj)->isArray() && oObj.arrayGetLength() == 4) if (oAnnot->dictLookup("Rect", &oObj)->isArray() && oObj.arrayGetLength() == 4)
{ {
@ -3239,6 +3351,90 @@ void CAnnotAP::Init(Object* oAnnot)
m_dx2 = ArrGetNum(&oObj, 2); m_dx2 = ArrGetNum(&oObj, 2);
m_dy2 = ArrGetNum(&oObj, 3); m_dy2 = ArrGetNum(&oObj, 3);
if (bIsStamp)
{
double m[6] = { 1, 0, 0, 1, 0, 0 }, bbox[4] = { m_dx1, m_dy1, m_dx2, m_dy2 };
oObj.free();
Object oAP;
if (oAnnot->dictLookup("AP", &oAP)->isDict() && oAP.dictLookup("N", &oObj2)->isStream())
{
Object oObj1;
if (oObj2.streamGetDict()->lookup("BBox", &oObj)->isArray() && oObj.arrayGetLength() == 4)
{
for (int i = 0; i < 4; ++i)
{
oObj.arrayGet(i, &oObj1);
bbox[i] = oObj1.isNum() ? oObj1.getNum() : 0;
oObj1.free();
}
}
oObj.free();
if (oObj2.streamGetDict()->lookup("Matrix", &oObj)->isArray() && oObj.arrayGetLength() == 6)
{
for (int i = 0; i < 6; ++i)
{
oObj.arrayGet(i, &oObj1);
m[i] = oObj1.getNum();
oObj1.free();
}
}
}
oAP.free(); oObj2.free();
double formXMin, formYMin, formXMax, formYMax, x, y, sx, sy;
x = bbox[0] * m[0] + bbox[1] * m[2] + m[4];
y = bbox[0] * m[1] + bbox[1] * m[3] + m[5];
formXMin = formXMax = x;
formYMin = formYMax = y;
x = bbox[0] * m[0] + bbox[3] * m[2] + m[4];
y = bbox[0] * m[1] + bbox[3] * m[3] + m[5];
if (x < formXMin)
formXMin = x;
else if (x > formXMax)
formXMax = x;
if (y < formYMin)
formYMin = y;
else if (y > formYMax)
formYMax = y;
x = bbox[2] * m[0] + bbox[1] * m[2] + m[4];
y = bbox[2] * m[1] + bbox[1] * m[3] + m[5];
if (x < formXMin)
formXMin = x;
else if (x > formXMax)
formXMax = x;
if (y < formYMin)
formYMin = y;
else if (y > formYMax)
formYMax = y;
x = bbox[2] * m[0] + bbox[3] * m[2] + m[4];
y = bbox[2] * m[1] + bbox[3] * m[3] + m[5];
if (x < formXMin)
formXMin = x;
else if (x > formXMax)
formXMax = x;
if (y < formYMin)
formYMin = y;
else if (y > formYMax)
formYMax = y;
if (formXMin == formXMax)
sx = 1;
else
sx = (m_dx2 - m_dx1) / (formXMax - formXMin);
if (formYMin == formYMax)
sy = 1;
else
sy = (m_dy2 - m_dy1) / (formYMax - formYMin);
m_dx1 = bbox[0];
m_dy1 = bbox[1];
m_dx2 = bbox[2];
m_dy2 = bbox[3];
dScale = std::max(sx, sy);
}
double dTemp; double dTemp;
if (m_dx1 > m_dx2) if (m_dx1 > m_dx2)
{ {
@ -3250,6 +3446,7 @@ void CAnnotAP::Init(Object* oAnnot)
} }
} }
oObj.free(); oObj.free();
return dScale;
} }
void CAnnotAP::Draw(PDFDoc* pdfDoc, Object* oAP, int nRasterH, int nBackgroundColor, int nPageIndex, AcroFormField* pField, const char* sView, const char* sButtonView) void CAnnotAP::Draw(PDFDoc* pdfDoc, Object* oAP, int nRasterH, int nBackgroundColor, int nPageIndex, AcroFormField* pField, const char* sView, const char* sButtonView)
{ {
@ -4007,5 +4204,14 @@ void CAnnotStamp::ToWASM(NSWasm::CData& oRes)
CAnnotMarkup::ToWASM(oRes); CAnnotMarkup::ToWASM(oRes);
oRes.WriteString(m_sName); oRes.WriteString(m_sName);
oRes.AddInt(m_nRotate);
oRes.WriteDouble(m_dX1);
oRes.WriteDouble(m_dY1);
oRes.WriteDouble(m_dX2);
oRes.WriteDouble(m_dY2);
oRes.WriteDouble(m_dX3);
oRes.WriteDouble(m_dY3);
oRes.WriteDouble(m_dX4);
oRes.WriteDouble(m_dY4);
} }
} }

View File

@ -136,7 +136,7 @@ private:
BYTE GetBlendMode(); BYTE GetBlendMode();
void Init(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex); void Init(PDFDoc* pdfDoc, NSFonts::IFontManager* pFontManager, CPdfFontList* pFontList, int nRasterW, int nRasterH, int nBackgroundColor, int nPageIndex);
void Init(AcroFormField* pField); void Init(AcroFormField* pField);
void Init(Object* oAnnot); double Init(Object* oAnnot);
void Draw(PDFDoc* pdfDoc, Object* oAP, int nRasterH, int nBackgroundColor, int nPageIndex, AcroFormField* pField, const char* sView, const char* sButtonView); void Draw(PDFDoc* pdfDoc, Object* oAP, int nRasterH, int nBackgroundColor, int nPageIndex, AcroFormField* pField, const char* sView, const char* sButtonView);
void Draw(PDFDoc* pdfDoc, Object* oAP, int nRasterH, int nBackgroundColor, Object* oAnnotRef, const char* sView); void Draw(PDFDoc* pdfDoc, Object* oAP, int nRasterH, int nBackgroundColor, Object* oAnnotRef, const char* sView);
void Clear(); void Clear();
@ -149,6 +149,7 @@ private:
double m_dHTale; double m_dHTale;
int m_nRx1, m_nRy1, m_nWidth, m_nHeight; int m_nRx1, m_nRy1, m_nWidth, m_nHeight;
std::vector<CAnnotAPView*> m_arrAP; std::vector<CAnnotAPView*> m_arrAP;
bool bIsStamp;
Gfx* m_gfx; Gfx* m_gfx;
CBgraFrame* m_pFrame; CBgraFrame* m_pFrame;
@ -176,6 +177,7 @@ protected:
unsigned int m_unFlags; unsigned int m_unFlags;
double m_dHeight; // Высота холста, для Y трансформации double m_dHeight; // Высота холста, для Y трансформации
double m_dX; // Смещение по X для трансформации double m_dX; // Смещение по X для трансформации
double m_pRect[4]; // Координаты
private: private:
struct CBorderType final struct CBorderType final
@ -197,7 +199,6 @@ private:
unsigned int m_unAnnotFlag; // Флаг аннотации - F unsigned int m_unAnnotFlag; // Флаг аннотации - F
unsigned int m_unRefNum; // Номер ссылки на объект unsigned int m_unRefNum; // Номер ссылки на объект
unsigned int m_unPage; // Страница unsigned int m_unPage; // Страница
double m_pRect[4]; // Координаты
std::pair<BYTE, double> m_pBE; // Эффекты границы std::pair<BYTE, double> m_pBE; // Эффекты границы
std::string m_sContents; // Отображаемый текст std::string m_sContents; // Отображаемый текст
std::string m_sNM; // Уникальное имя std::string m_sNM; // Уникальное имя
@ -577,6 +578,8 @@ public:
void ToWASM(NSWasm::CData& oRes) override; void ToWASM(NSWasm::CData& oRes) override;
private: private:
std::string m_sName; // Иконка std::string m_sName; // Иконка
int m_nRotate;
double m_dX1, m_dY1, m_dX2, m_dY2, m_dX3, m_dY3, m_dX4, m_dY4;
}; };
//------------------------------------------------------------------------ //------------------------------------------------------------------------

View File

@ -1574,6 +1574,13 @@ void Annot::draw(Gfx *gfx, GBool printing) {
// draw the appearance stream // draw the appearance stream
isLink = type && !type->cmp("Link"); isLink = type && !type->cmp("Link");
#ifdef BUILDING_WASM_MODULE
if (type && !type->cmp("Stamp"))
{
gfx->drawStamp(&appearance);
return;
}
#endif
gfx->drawAnnot(&appearance, isLink ? borderStyle : (AnnotBorderStyle *)NULL, gfx->drawAnnot(&appearance, isLink ? borderStyle : (AnnotBorderStyle *)NULL,
xMin, yMin, xMax, yMax); xMin, yMin, xMax, yMax);
} }

View File

@ -5318,6 +5318,54 @@ void Gfx::drawAnnot(Object *strRef, AnnotBorderStyle *borderStyle,
} }
} }
void Gfx::drawStamp(Object *strRef)
{
Dict *dict, *resDict;
Object str, bboxObj, resObj, obj1;
double m[6], bbox[4];
int i;
// draw the appearance stream (if there is one)
strRef->fetch(xref, &str);
if (str.isStream()) {
// get stream dict
dict = str.streamGetDict();
// get the form bounding box
dict->lookup("BBox", &bboxObj);
if (!bboxObj.isArray() || bboxObj.arrayGetLength() != 4) {
error(errSyntaxError, getPos(), "Bad form bounding box");
bboxObj.free();
str.free();
return;
}
for (i = 0; i < 4; ++i) {
bboxObj.arrayGet(i, &obj1);
if (obj1.isNum()) {
bbox[i] = obj1.getNum();
} else {
bbox[i] = 0;
}
obj1.free();
}
bboxObj.free();
m[0] = 1; m[1] = 0;
m[2] = 0; m[3] = 1;
m[4] = 0; m[5] = 0;
// get the resources
dict->lookup("Resources", &resObj);
resDict = resObj.isDict() ? resObj.getDict() : (Dict *)NULL;
// draw it
drawForm(strRef, resDict, m, bbox);
resObj.free();
}
str.free();
}
void Gfx::saveState() { void Gfx::saveState() {
out->saveState(state); out->saveState(state);
state = state->save(); state = state->save();

View File

@ -153,6 +153,7 @@ public:
// border style, and bounding box (in default user space). // border style, and bounding box (in default user space).
void drawAnnot(Object *strRef, AnnotBorderStyle *borderStyle, void drawAnnot(Object *strRef, AnnotBorderStyle *borderStyle,
double xMin, double yMin, double xMax, double yMax); double xMin, double yMin, double xMax, double yMax);
void drawStamp(Object *strRef);
// Save graphics state. // Save graphics state.
void saveState(); void saveState();