Fix text color

This commit is contained in:
Svetlana Kulikova
2025-09-30 18:41:22 +03:00
parent a8d34f2437
commit 5cf633ede6
8 changed files with 122 additions and 77 deletions

View File

@ -520,6 +520,7 @@ namespace PdfWriter
m_unShadingsCount = 0;
m_pPatterns = NULL;
m_unPatternsCount = 0;
m_eType = fontUnknownType;
}
void CPage::SetWidth(double dValue)
{
@ -1281,26 +1282,24 @@ namespace PdfWriter
}
void CPage::WriteText(const BYTE* sText, unsigned int unLen)
{
EFontType eType = m_pFont ? m_pFont->GetFontType() : fontCIDType0;
EFontType eType = m_eType != fontUnknownType ? m_eType : (m_pFont ? m_pFont->GetFontType() : fontCIDType0);
if (fontCIDType0 == eType || fontCIDType0C == eType || fontCIDType0COT == eType || fontCIDType2 == eType || fontCIDType2OT == eType)
{
m_pStream->WriteChar('<');
m_pStream->WriteBinary(sText, unLen, NULL);
m_pStream->WriteChar('>');
}
else if (fontType1 == eType)
else
{
unLen = unLen / 2;
BYTE* sText2 = new BYTE[unLen];
for (int i = 0; i < unLen; ++i)
sText2[i] = sText[i * 2 + 1];
m_pStream->WriteEscapeText(sText2, unLen);
m_pStream->WriteChar('<');
m_pStream->WriteBinary(sText2, unLen, NULL);
m_pStream->WriteChar('>');
RELEASEARRAYOBJECTS(sText2);
}
else
{
m_pStream->WriteEscapeText(sText, unLen);
}
}
void CPage::DrawText(double dXpos, double dYpos, const BYTE* sText, unsigned int unLen)
{
@ -1448,6 +1447,10 @@ namespace PdfWriter
m_pStream->WriteReal(dSize);
m_pStream->WriteStr(" Tf\012");
}
void CPage::SetFontType(EFontType nType)
{
m_eType = nType;
}
void CPage::SetTextRenderingMode(ETextRenderingMode eMode)
{
// Operator : Tr

View File

@ -174,6 +174,7 @@ namespace PdfWriter
void SetHorizontalScaling(double dValue);
void SetFontAndSize(CFontDict* pFont, double dSize);
void SetFontKeyAndSize(const char* sKey, double dSize);
void SetFontType(EFontType nType);
void SetTextRenderingMode(ETextRenderingMode eMode);
void SetTextMatrix(double dM11, double dM12, double dM21, double dM22, double dX, double dY);
void DrawTextLine(const CTextLine* pTextLine);
@ -228,6 +229,7 @@ namespace PdfWriter
unsigned int m_unShadingsCount;
CDictObject* m_pPatterns;
unsigned int m_unPatternsCount;
EFontType m_eType;
};
class CFakePage : public CObjectBase
{

View File

@ -379,7 +379,34 @@ void RedactOutputDev::clipToStrokePath(GfxState *pGState)
//----- text drawing
void RedactOutputDev::beginStringOp(GfxState *pGState)
{
int nDColor2Size;
double* dColor = m_pRenderer->m_oBrush.GetDColor2(nDColor2Size);
if (nDColor2Size == 1)
m_pPage->SetFillG(dColor[0]);
else if (nDColor2Size == 3)
m_pPage->SetFillRGB(dColor[0], dColor[1], dColor[2]);
else if (nDColor2Size == 4)
m_pPage->SetFillCMYK(dColor[0], dColor[1], dColor[2], dColor[3]);
dColor = m_pRenderer->m_oPen.GetDColor2(nDColor2Size);
if (nDColor2Size == 1)
m_pPage->SetStrokeG(dColor[0]);
else if (nDColor2Size == 3)
m_pPage->SetStrokeRGB(dColor[0], dColor[1], dColor[2]);
else if (nDColor2Size == 4)
m_pPage->SetStrokeCMYK(dColor[0], dColor[1], dColor[2], dColor[3]);
CStream* pStream = m_pPage->GetStream();
for (int i = 0; i < m_sStates.size(); ++i)
{
for (int j = 0; j < m_sStates[i].m_arrOp.size(); ++j)
{
pStream->WriteStr(m_sStates[i].m_arrOp[j].first.c_str());
pStream->WriteChar(' ');
pStream->WriteStr(m_sStates[i].m_arrOp[j].second.c_str());
pStream->WriteStr("\012");
}
}
}
void RedactOutputDev::endStringOp(GfxState *pGState)
{
@ -454,7 +481,11 @@ void RedactOutputDev::drawChar(GfxState *pGState, double dX, double dY, double d
double dShiftX = 0, dShiftY = 0;
DoTransform(arrMatrix, &dShiftX, &dShiftY, true);
double dDiff = dX + dDx / 2.0;
double startX, startY, endX, endY;
pGState->transform(dX, dY, &startX, &startY);
pGState->transform(dX + dDx, dY + dDy, &endX, &endY);
double dCenterX = (startX + endX) / 2;
double dCenterY = (startY + endY) / 2;
for (int i = 0; i < m_arrQuadPoints.size(); i += 4)
{
double xMin = m_arrQuadPoints[i + 0];
@ -462,8 +493,11 @@ void RedactOutputDev::drawChar(GfxState *pGState, double dX, double dY, double d
double xMax = m_arrQuadPoints[i + 2];
double yMax = m_arrQuadPoints[i + 3];
if (xMin < dDiff && dDiff < xMax && yMin < dY && dY < yMax)
if (xMin < dCenterX && dCenterX < xMax && yMin < dCenterY && dCenterY < yMax)
{
m_pRenderer->put_FontSize(dOldSize);
return;
}
}
BYTE* pCodes = new BYTE[2];
@ -475,9 +509,7 @@ void RedactOutputDev::drawChar(GfxState *pGState, double dX, double dY, double d
CRendererTextCommand* pText = m_pRenderer->m_oCommandManager.AddText(pCodes, 2, dShiftX, dShiftY);
pText->SetName(m_pRenderer->m_oFont.GetName());
pText->SetSize(m_pRenderer->m_oFont.GetSize());
int nDColor2Size;
double* dColor2 = m_pRenderer->m_oBrush.GetDColor2(nDColor2Size);
pText->SetDColor2(nDColor2Size, dColor2[0], dColor2[1], dColor2[2], dColor2[3]);
pText->SetType((EFontType)pGState->getFont()->getType());
pText->SetAlpha((BYTE)m_pRenderer->m_oBrush.GetAlpha1()); // TODO
pText->SetCharSpace(m_pRenderer->m_oFont.GetCharSpace());
pText->SetMode(m_pRenderer->m_oFont.GetRenderMode());
@ -485,6 +517,8 @@ void RedactOutputDev::drawChar(GfxState *pGState, double dX, double dY, double d
pText->SetWordSpace(m_pRenderer->m_oFont.GetWordSpace());
pText->SetHorScaling(m_pRenderer->m_oFont.GetHorizontalScaling());
pText->SetWidth(dDx);
m_pRenderer->put_FontSize(dOldSize);
}
GBool RedactOutputDev::beginType3Char(GfxState *pGState, double x, double y, double dx, double dy, CharCode code, Unicode *u, int uLen)
{
@ -527,13 +561,15 @@ void RedactOutputDev::setExtGState(const char* name)
{
if (m_sStates.empty())
return;
m_sStates.back().m_arrOp.push_back(std::make_pair("/" + std::string(name), "gs"));
std::string sOp = "/" + std::string(name);
m_sStates.back().m_arrOp.push_back(std::make_pair(sOp, "gs"));
}
void RedactOutputDev::setFillColorSpace(const char* name)
{
if (m_sStates.empty())
return;
m_sStates.back().m_arrOp.push_back(std::make_pair("/" + std::string(name), "cs"));
std::string sOp = "/" + std::string(name);
m_sStates.back().m_arrOp.push_back(std::make_pair(sOp, "cs"));
}
void RedactOutputDev::setFillColorN(Object* args, int numArgs)
{
@ -551,6 +587,34 @@ void RedactOutputDev::setFillColorN(Object* args, int numArgs)
}
m_sStates.back().m_arrOp.push_back(std::make_pair(sOp, "scn"));
}
void RedactOutputDev::setShading(GfxState *pGState, const char* name)
{
m_pRenderer->m_oCommandManager.Flush();
double dShiftX = 0, dShiftY = 0;
DoTransform(pGState->getCTM(), &dShiftX, &dShiftY, true);
// TODO Нужно проверять Shading на отсечение?
m_pPage->GrSave();
UpdateTransform();
CStream* pStream = m_pPage->GetStream();
for (int i = 0; i < m_sStates.size(); ++i)
{
for (int j = 0; j < m_sStates[i].m_arrOp.size(); ++j)
{
pStream->WriteStr(m_sStates[i].m_arrOp[j].first.c_str());
pStream->WriteChar(' ');
pStream->WriteStr(m_sStates[i].m_arrOp[j].second.c_str());
pStream->WriteStr("\012");
}
}
pStream->WriteEscapeName(name);
pStream->WriteChar(' ');
pStream->WriteStr("sh");
pStream->WriteStr("\012");
m_pPage->GrRestore();
}
//----- image drawing
void RedactOutputDev::drawImageMask(GfxState *pGState, Object *pRef, Stream *pStream, int nWidth, int nHeight, GBool bInvert, GBool bInlineImage, GBool interpolate)
{
@ -659,54 +723,22 @@ void RedactOutputDev::drawImage(GfxState *pGState, Ref id, const char* name)
DoTransform(pGState->getCTM(), &dShiftX, &dShiftY, true);
// TODO пока что исключается всё изображение
Object oImage;
if (!m_pXref->fetch(id.num, id.gen, &oImage)->isStream())
{
oImage.free();
return;
}
// TODO нужно учитывать Matrix у формы
Dict* pDict = oImage.streamGetDict();
Object obj1;
if (pDict->lookup("Width", &obj1)->isNull())
{
obj1.free();
if (!pDict->lookup("W", &obj1)->isNum())
{
obj1.free(); oImage.free();
return;
}
}
double width = obj1.getNum();
obj1.free();
if (width <= 0)
{
oImage.free();
return;
}
if (pDict->lookup("Height", &obj1)->isNull())
{
obj1.free();
if (!pDict->lookup("H", &obj1)->isNum())
{
obj1.free(); oImage.free();
return;
}
}
double height = obj1.getNum();
obj1.free();
if (height <= 0)
{
oImage.free();
return;
}
double dXmin = 0, dYmin = 0, dXmax = width, dYmax = height;
double dXmin = 0, dYmin = 0, dXmax = 1, dYmax = 1;
Transform(m_arrMatrix, dXmin, dYmin, &dXmin, &dYmin);
Transform(m_arrMatrix, dXmax, dYmax, &dXmax, &dYmax);
for (int i = 0; i < m_arrQuadPoints.size(); i += 4)
{
double xMin = m_arrQuadPoints[i + 0];
double yMin = m_arrQuadPoints[i + 1];
double xMax = m_arrQuadPoints[i + 2];
double yMax = m_arrQuadPoints[i + 3];
if (!(dXmax < xMin || dXmin > xMax || dYmax < yMin || dYmin > yMax))
return;
}
m_pPage->GrSave();
UpdateTransform();
CStream* pStream = m_pPage->GetStream();
@ -720,22 +752,6 @@ void RedactOutputDev::drawImage(GfxState *pGState, Ref id, const char* name)
pStream->WriteStr("\012");
}
}
for (int i = 0; i < m_arrQuadPoints.size(); i += 4)
{
double xMin = m_arrQuadPoints[i + 0];
double yMin = m_arrQuadPoints[i + 1];
double xMax = m_arrQuadPoints[i + 2];
double yMax = m_arrQuadPoints[i + 3];
if (!(dXmax < xMin || dXmin > xMax || dYmax < yMin || dYmin > yMax))
{
m_pPage->GrRestore();
return;
}
}
oImage.free();
m_pPage->ExecuteXObject(name);
m_pPage->GrRestore();
}
@ -1416,9 +1432,10 @@ void RedactOutputDev::DrawPath(const LONG& lType)
{
pStream->WriteStr(m_sStates[i].m_arrOp[j].first.c_str());
pStream->WriteChar(' ');
pStream->WriteStr(m_sStates[i].m_arrOp[j].second.c_str());
std::string sOp = m_sStates[i].m_arrOp[j].second;
pStream->WriteStr(sOp.c_str());
pStream->WriteStr("\012");
if (m_sStates[i].m_arrOp[j].second == "cs")
if (sOp == "cs" || sOp == "sc" || sOp == "scn")
bCS = true;
}
}

View File

@ -157,6 +157,7 @@ namespace PdfWriter
virtual void setExtGState(const char* name) override;
virtual void setFillColorSpace(const char* name) override;
virtual void setFillColorN(Object* args, int numArgs) override;
virtual void setShading(GfxState *state, const char* name) override;
//----- image drawing
virtual void drawImageMask(GfxState *pGState, Object *pRef, Stream *pStream, int nWidth, int nHeight, GBool bInvert, GBool bInlineImage, GBool interpolate) override;
virtual void setSoftMaskFromImageMask(GfxState *pGState, Object *pRef, Stream *pStream, int nWidth, int nHeight, GBool bInvert, GBool bInlineImage, GBool interpolate) override;

View File

@ -35,6 +35,7 @@
#include "Pages.h"
#include "FontCidTT.h"
#include "../PdfWriter.h"
#include "Streams.h"
//----------------------------------------------------------------------------------------
//
@ -120,6 +121,7 @@ void CCommandManager::Flush()
{
std::string sKey = U_TO_UTF8(sTextName);
pPage->SetFontKeyAndSize(sKey.c_str(), dTextSize);
pPage->SetFontType(pText->GetFontType());
}
}
@ -132,6 +134,7 @@ void CCommandManager::Flush()
oTextLine.Flush(pPage);
nColorSize = nColorSize2;
dColor[0] = dColor2[0];
pPage->SetFillG(dColor[0]);
pPage->SetStrokeG(dColor[0]);
}
else if (nColorSize2 == 3 && (nColorSize != nColorSize2 || dColor[0] != dColor2[0] || dColor[1] != dColor2[1] || dColor[2] != dColor2[2]))
@ -141,6 +144,7 @@ void CCommandManager::Flush()
dColor[0] = dColor2[0];
dColor[1] = dColor2[1];
dColor[2] = dColor2[2];
pPage->SetFillRGB(dColor[0], dColor[1], dColor[2]);
pPage->SetStrokeRGB(dColor[0], dColor[1], dColor[2]);
}
else if (nColorSize2 == 4 && (nColorSize != nColorSize2 || dColor[0] != dColor2[0] || dColor[1] != dColor2[1] || dColor[2] != dColor2[2] || dColor[3] != dColor2[3]))
@ -151,6 +155,7 @@ void CCommandManager::Flush()
dColor[1] = dColor2[1];
dColor[2] = dColor2[2];
dColor[3] = dColor2[3];
pPage->SetFillCMYK(dColor[0], dColor[1], dColor[2], dColor[3]);
pPage->SetStrokeCMYK(dColor[0], dColor[1], dColor[2], dColor[3]);
}
}

View File

@ -73,6 +73,7 @@ public:
m_dY = dY;
m_pFont = NULL;
m_dSize = -1;
m_nType = PdfWriter::EFontType::fontUnknownType;
m_lColor = 0;
m_nAlpha = 255;
m_dCharSpace = 0;
@ -121,6 +122,10 @@ public:
{
m_dSize = dSize;
}
inline void SetType(PdfWriter::EFontType oType)
{
m_nType = oType;
}
inline void SetColor(const LONG& lColor)
{
m_lColor = lColor;
@ -185,6 +190,10 @@ public:
{
return m_dSize;
}
inline PdfWriter::EFontType GetFontType() const
{
return m_nType;
}
inline LONG GetColor() const
{
return m_lColor;
@ -250,6 +259,7 @@ private:
bool m_bNeedDoItalic;
bool m_bNeedDoBold;
double m_dSize;
PdfWriter::EFontType m_nType;
LONG m_lColor;
BYTE m_nAlpha;
double m_dCharSpace;
@ -1634,7 +1644,7 @@ private:
private:
CPdfWriter* m_pRenderer;
std::vector<CRendererCommandBase*> m_vCommands;
CTransform m_oTransform;
CTransform m_oTransform;
};
struct TDestinationInfo
{

View File

@ -2370,6 +2370,12 @@ void Gfx::opShFill(Object args[], int numArgs) {
return;
}
if (out->useNameOp())
{
out->setShading(state, args[0].getName());
return;
}
// save current graphics state
savedState = saveStateStack();

View File

@ -194,6 +194,7 @@ public:
virtual void setExtGState(const char* name) {}
virtual void setFillColorSpace(const char* name) {}
virtual void setFillColorN(Object* args, int numArgs) {}
virtual void setShading(GfxState *state, const char* name) {}
//----- image drawing
virtual void drawImageMask(GfxState *state, Object *ref, Stream *str,