summaryrefslogtreecommitdiff
path: root/core/fxge/win32/cfx_psrenderer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'core/fxge/win32/cfx_psrenderer.cpp')
-rw-r--r--core/fxge/win32/cfx_psrenderer.cpp274
1 files changed, 141 insertions, 133 deletions
diff --git a/core/fxge/win32/cfx_psrenderer.cpp b/core/fxge/win32/cfx_psrenderer.cpp
index 46af33710c..ba027ba6dc 100644
--- a/core/fxge/win32/cfx_psrenderer.cpp
+++ b/core/fxge/win32/cfx_psrenderer.cpp
@@ -19,6 +19,60 @@
#include "core/fxge/win32/cpsoutput.h"
#include "third_party/base/ptr_util.h"
+namespace {
+
+void FaxCompressData(uint8_t* src_buf,
+ int width,
+ int height,
+ std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
+ uint32_t* dest_size) {
+ if (width * height > 128) {
+ CCodec_FaxModule::FaxEncode(src_buf, width, height, (width + 7) / 8,
+ dest_buf, dest_size);
+ FX_Free(src_buf);
+ } else {
+ dest_buf->reset(src_buf);
+ *dest_size = (width + 7) / 8 * height;
+ }
+}
+
+void PSCompressData(int PSLevel,
+ uint8_t* src_buf,
+ uint32_t src_size,
+ uint8_t** output_buf,
+ uint32_t* output_size,
+ const char** filter) {
+ *output_buf = src_buf;
+ *output_size = src_size;
+ *filter = "";
+ if (src_size < 1024)
+ return;
+
+ CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule();
+ uint8_t* dest_buf = nullptr;
+ uint32_t dest_size = src_size;
+ if (PSLevel >= 3) {
+ if (pEncoders && pEncoders->GetFlateModule()->Encode(
+ src_buf, src_size, &dest_buf, &dest_size)) {
+ *filter = "/FlateDecode filter ";
+ }
+ } else {
+ if (pEncoders && pEncoders->GetBasicModule()->RunLengthEncode(
+ src_buf, src_size, &dest_buf, &dest_size)) {
+ *filter = "/RunLengthDecode filter ";
+ }
+ }
+ if (dest_size < src_size) {
+ *output_buf = dest_buf;
+ *output_size = dest_size;
+ } else {
+ *filter = nullptr;
+ FX_Free(dest_buf);
+ }
+}
+
+} // namespace
+
struct PSGlyph {
CFX_Font* m_pFont;
uint32_t m_GlyphIndex;
@@ -32,33 +86,32 @@ class CPSFont {
int m_nGlyphs;
};
-CFX_PSRenderer::CFX_PSRenderer() {
- m_pOutput = nullptr;
- m_bColorSet = m_bGraphStateSet = false;
- m_bInited = false;
-}
+CFX_PSRenderer::CFX_PSRenderer()
+ : m_pStream(nullptr),
+ m_bGraphStateSet(false),
+ m_bColorSet(false),
+ m_bInited(false) {}
CFX_PSRenderer::~CFX_PSRenderer() {}
-#define OUTPUT_PS(str) m_pOutput->OutputPS(str, sizeof(str) - 1)
-
-void CFX_PSRenderer::Init(CPSOutput* pOutput,
+void CFX_PSRenderer::Init(const CFX_RetainPtr<IFX_WriteStream>& pStream,
int pslevel,
int width,
int height,
bool bCmykOutput) {
m_PSLevel = pslevel;
- m_pOutput = pOutput;
- m_ClipBox.left = m_ClipBox.top = 0;
+ m_pStream = pStream;
+ m_ClipBox.left = 0;
+ m_ClipBox.top = 0;
m_ClipBox.right = width;
m_ClipBox.bottom = height;
m_bCmykOutput = bCmykOutput;
}
bool CFX_PSRenderer::StartRendering() {
- if (m_bInited) {
+ if (m_bInited)
return true;
- }
+
static const char init_str[] =
"\nsave\n/im/initmatrix load def\n"
"/n/newpath load def/m/moveto load def/l/lineto load def/c/curveto load "
@@ -73,30 +126,30 @@ bool CFX_PSRenderer::StartRendering() {
"load def\n"
"/cm/concat load def/Cm/currentmatrix load def/mx/matrix load "
"def/sm/setmatrix load def\n";
- OUTPUT_PS(init_str);
+ m_pStream->WriteString(init_str);
m_bInited = true;
return true;
}
void CFX_PSRenderer::EndRendering() {
- if (m_bInited) {
- OUTPUT_PS("\nrestore\n");
- m_bInited = false;
- }
+ if (!m_bInited)
+ return;
+
+ m_pStream->WriteString("\nrestore\n");
+ m_bInited = false;
}
void CFX_PSRenderer::SaveState() {
StartRendering();
- OUTPUT_PS("q\n");
+ m_pStream->WriteString("q\n");
m_ClipBoxStack.push_back(m_ClipBox);
}
void CFX_PSRenderer::RestoreState(bool bKeepSaved) {
StartRendering();
+ m_pStream->WriteString("Q\n");
if (bKeepSaved)
- OUTPUT_PS("Q\nq\n");
- else
- OUTPUT_PS("Q\n");
+ m_pStream->WriteString("q\n");
m_bColorSet = false;
m_bGraphStateSet = false;
@@ -148,7 +201,7 @@ void CFX_PSRenderer::OutputPath(const CFX_PathData* pPathData,
}
}
}
- m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize());
+ m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize());
}
void CFX_PSRenderer::SetClip_PathFill(const CFX_PathData* pPathData,
@@ -164,11 +217,11 @@ void CFX_PSRenderer::SetClip_PathFill(const CFX_PathData* pPathData,
m_ClipBox.right = static_cast<int>(rect.left + rect.right);
m_ClipBox.top = static_cast<int>(rect.top + rect.bottom);
m_ClipBox.bottom = static_cast<int>(rect.bottom);
- if ((fill_mode & 3) == FXFILL_WINDING) {
- OUTPUT_PS("W n\n");
- } else {
- OUTPUT_PS("W* n\n");
- }
+
+ m_pStream->WriteString("W");
+ if ((fill_mode & 3) != FXFILL_WINDING)
+ m_pStream->WriteString("*");
+ m_pStream->WriteString(" n\n");
}
void CFX_PSRenderer::SetClip_PathStroke(const CFX_PathData* pPathData,
@@ -181,18 +234,19 @@ void CFX_PSRenderer::SetClip_PathStroke(const CFX_PathData* pPathData,
buf << "mx Cm [" << pObject2Device->a << " " << pObject2Device->b << " "
<< pObject2Device->c << " " << pObject2Device->d << " "
<< pObject2Device->e << " " << pObject2Device->f << "]cm ";
- m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize());
+ m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize());
}
+
OutputPath(pPathData, nullptr);
CFX_FloatRect rect = pPathData->GetBoundingBox(pGraphState->m_LineWidth,
pGraphState->m_MiterLimit);
pObject2Device->TransformRect(rect);
m_ClipBox.Intersect(rect.GetOuterRect());
- if (pObject2Device) {
- OUTPUT_PS("strokepath W n sm\n");
- } else {
- OUTPUT_PS("strokepath W n\n");
- }
+
+ m_pStream->WriteString("strokepath W n");
+ if (pObject2Device)
+ m_pStream->WriteString(" sm");
+ m_pStream->WriteString("\n");
}
bool CFX_PSRenderer::DrawPath(const CFX_PathData* pPathData,
@@ -204,15 +258,13 @@ bool CFX_PSRenderer::DrawPath(const CFX_PathData* pPathData,
StartRendering();
int fill_alpha = FXARGB_A(fill_color);
int stroke_alpha = FXARGB_A(stroke_color);
- if (fill_alpha && fill_alpha < 255) {
+ if (fill_alpha && fill_alpha < 255)
return false;
- }
- if (stroke_alpha && stroke_alpha < 255) {
+ if (stroke_alpha && stroke_alpha < 255)
return false;
- }
- if (fill_alpha == 0 && stroke_alpha == 0) {
+ if (fill_alpha == 0 && stroke_alpha == 0)
return false;
- }
+
if (stroke_alpha) {
SetGraphState(pGraphState);
if (pObject2Device) {
@@ -220,35 +272,34 @@ bool CFX_PSRenderer::DrawPath(const CFX_PathData* pPathData,
buf << "mx Cm [" << pObject2Device->a << " " << pObject2Device->b << " "
<< pObject2Device->c << " " << pObject2Device->d << " "
<< pObject2Device->e << " " << pObject2Device->f << "]cm ";
- m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize());
+ m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize());
}
}
+
OutputPath(pPathData, stroke_alpha ? nullptr : pObject2Device);
if (fill_mode && fill_alpha) {
SetColor(fill_color);
if ((fill_mode & 3) == FXFILL_WINDING) {
- if (stroke_alpha) {
- OUTPUT_PS("q f Q ");
- } else {
- OUTPUT_PS("f");
- }
+ if (stroke_alpha)
+ m_pStream->WriteString("q f Q ");
+ else
+ m_pStream->WriteString("f");
} else if ((fill_mode & 3) == FXFILL_ALTERNATE) {
- if (stroke_alpha) {
- OUTPUT_PS("q F Q ");
- } else {
- OUTPUT_PS("F");
- }
+ if (stroke_alpha)
+ m_pStream->WriteString("q F Q ");
+ else
+ m_pStream->WriteString("F");
}
}
+
if (stroke_alpha) {
SetColor(stroke_color);
- if (pObject2Device) {
- OUTPUT_PS("s sm");
- } else {
- OUTPUT_PS("s");
- }
+ m_pStream->WriteString("s");
+ if (pObject2Device)
+ m_pStream->WriteString(" sm");
}
- OUTPUT_PS("\n");
+
+ m_pStream->WriteString("\n");
return true;
}
@@ -263,9 +314,9 @@ void CFX_PSRenderer::SetGraphState(const CFX_GraphStateData* pGraphState) {
memcmp(m_CurGraphState.m_DashArray, pGraphState->m_DashArray,
sizeof(float) * m_CurGraphState.m_DashCount)) {
buf << "[";
- for (int i = 0; i < pGraphState->m_DashCount; ++i) {
+ for (int i = 0; i < pGraphState->m_DashCount; ++i)
buf << pGraphState->m_DashArray[i] << " ";
- }
+
buf << "]" << pGraphState->m_DashPhase << " d\n";
}
if (!m_bGraphStateSet ||
@@ -282,61 +333,8 @@ void CFX_PSRenderer::SetGraphState(const CFX_GraphStateData* pGraphState) {
}
m_CurGraphState.Copy(*pGraphState);
m_bGraphStateSet = true;
- if (buf.GetSize()) {
- m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize());
- }
-}
-
-static void FaxCompressData(uint8_t* src_buf,
- int width,
- int height,
- std::unique_ptr<uint8_t, FxFreeDeleter>* dest_buf,
- uint32_t* dest_size) {
- if (width * height > 128) {
- CCodec_FaxModule::FaxEncode(src_buf, width, height, (width + 7) / 8,
- dest_buf, dest_size);
- FX_Free(src_buf);
- } else {
- dest_buf->reset(src_buf);
- *dest_size = (width + 7) / 8 * height;
- }
-}
-
-static void PSCompressData(int PSLevel,
- uint8_t* src_buf,
- uint32_t src_size,
- uint8_t** output_buf,
- uint32_t* output_size,
- const char** filter) {
- *output_buf = src_buf;
- *output_size = src_size;
- *filter = "";
- if (src_size < 1024) {
- return;
- }
- CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule();
- uint8_t* dest_buf = nullptr;
- uint32_t dest_size = src_size;
- if (PSLevel >= 3) {
- if (pEncoders &&
- pEncoders->GetFlateModule()->Encode(src_buf, src_size, &dest_buf,
- &dest_size)) {
- *filter = "/FlateDecode filter ";
- }
- } else {
- if (pEncoders &&
- pEncoders->GetBasicModule()->RunLengthEncode(src_buf, src_size,
- &dest_buf, &dest_size)) {
- *filter = "/RunLengthDecode filter ";
- }
- }
- if (dest_size < src_size) {
- *output_buf = dest_buf;
- *output_size = dest_size;
- } else {
- *filter = nullptr;
- FX_Free(dest_buf);
- }
+ if (buf.GetSize())
+ m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize());
}
bool CFX_PSRenderer::SetDIBits(const CFX_RetainPtr<CFX_DIBSource>& pSource,
@@ -372,20 +370,23 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_RetainPtr<CFX_DIBSource>& pSource,
(pMatrix->c == 0 && pMatrix->d == 0)) {
return true;
}
- if (pSource->HasAlpha()) {
+ if (pSource->HasAlpha())
return false;
- }
+
int alpha = FXARGB_A(color);
if (pSource->IsAlphaMask() && (alpha < 255 || pSource->GetBPP() != 1))
return false;
- OUTPUT_PS("q\n");
+ m_pStream->WriteString("q\n");
+
CFX_ByteTextBuf buf;
buf << "[" << pMatrix->a << " " << pMatrix->b << " " << pMatrix->c << " "
<< pMatrix->d << " " << pMatrix->e << " " << pMatrix->f << "]cm ";
+
int width = pSource->GetWidth();
int height = pSource->GetHeight();
buf << width << " " << height;
+
if (pSource->GetBPP() == 1 && !pSource->GetPalette()) {
int pitch = (width + 7) / 8;
uint32_t src_size = height * pitch;
@@ -394,6 +395,7 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_RetainPtr<CFX_DIBSource>& pSource,
const uint8_t* src_scan = pSource->GetScanline(row);
memcpy(src_buf + row * pitch, src_scan, pitch);
}
+
std::unique_ptr<uint8_t, FxFreeDeleter> output_buf;
uint32_t output_size;
FaxCompressData(src_buf, width, height, &output_buf, &output_size);
@@ -406,16 +408,17 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_RetainPtr<CFX_DIBSource>& pSource,
}
buf << width << " 0 0 -" << height << " 0 " << height
<< "]currentfile/ASCII85Decode filter ";
+
if (output_buf.get() != src_buf) {
buf << "<</K -1/EndOfBlock false/Columns " << width << "/Rows " << height
<< ">>/CCITTFaxDecode filter ";
}
- if (pSource->IsAlphaMask()) {
+ if (pSource->IsAlphaMask())
buf << "iM\n";
- } else {
+ else
buf << "false 1 colorimage\n";
- }
- m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize());
+
+ m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize());
WritePSBinary(output_buf.get(), output_size);
output_buf.release();
} else {
@@ -445,9 +448,10 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_RetainPtr<CFX_DIBSource>& pSource,
break;
}
if (!pConverted) {
- OUTPUT_PS("\nQ\n");
+ m_pStream->WriteString("\nQ\n");
return false;
}
+
int bpp = pConverted->GetBPP() / 8;
uint8_t* output_buf = nullptr;
FX_STRSIZE output_size = 0;
@@ -478,25 +482,26 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_RetainPtr<CFX_DIBSource>& pSource,
uint32_t compressed_size;
PSCompressData(m_PSLevel, output_buf, output_size, &compressed_buf,
&compressed_size, &filter);
- if (output_buf != compressed_buf) {
+ if (output_buf != compressed_buf)
FX_Free(output_buf);
- }
+
output_buf = compressed_buf;
output_size = compressed_size;
}
buf << " 8[";
buf << width << " 0 0 -" << height << " 0 " << height << "]";
buf << "currentfile/ASCII85Decode filter ";
- if (filter) {
+ if (filter)
buf << filter;
- }
+
buf << "false " << bpp;
buf << " colorimage\n";
- m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize());
+ m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize());
+
WritePSBinary(output_buf, output_size);
FX_Free(output_buf);
}
- OUTPUT_PS("\nQ\n");
+ m_pStream->WriteString("\nQ\n");
return true;
}
@@ -517,7 +522,7 @@ void CFX_PSRenderer::SetColor(uint32_t color) {
m_bColorSet = true;
m_LastColor = color;
}
- m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize());
+ m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize());
}
}
@@ -548,6 +553,7 @@ void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache,
}
++i;
}
+
if (m_PSFontList.empty() || m_PSFontList.back()->m_nGlyphs == 256) {
m_PSFontList.push_back(pdfium::MakeUnique<CPSFont>());
m_PSFontList.back()->m_nGlyphs = 0;
@@ -563,9 +569,10 @@ void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache,
"currentdict end\n";
buf << "/X" << static_cast<uint32_t>(m_PSFontList.size() - 1)
<< " exch definefont pop\n";
- m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize());
+ m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize());
buf.Clear();
}
+
*ps_fontnum = m_PSFontList.size() - 1;
CPSFont* pPSFont = m_PSFontList[*ps_fontnum].get();
int glyphindex = pPSFont->m_nGlyphs;
@@ -624,7 +631,7 @@ void CFX_PSRenderer::FindPSFontGlyph(CFX_FaceCache* pFaceCache,
buf << "f}bind def end\n";
buf << "/X" << *ps_fontnum << " Ff/Encoding get " << glyphindex << "/"
<< glyphindex << " put\n";
- m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize());
+ m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize());
}
bool CFX_PSRenderer::DrawText(int nChars,
@@ -642,6 +649,7 @@ bool CFX_PSRenderer::DrawText(int nChars,
(pObject2Device->c == 0 && pObject2Device->d == 0)) {
return true;
}
+
SetColor(color);
CFX_ByteTextBuf buf;
buf << "q[" << pObject2Device->a << " " << pObject2Device->b << " "
@@ -665,7 +673,7 @@ bool CFX_PSRenderer::DrawText(int nChars,
buf << hex.AsStringC() << "Tj\n";
}
buf << "Q\n";
- m_pOutput->OutputPS((const char*)buf.GetBuffer(), buf.GetSize());
+ m_pStream->WriteBlock(buf.GetBuffer(), buf.GetSize());
pCache->ReleaseCachedFace(pFont);
return true;
}
@@ -677,9 +685,9 @@ void CFX_PSRenderer::WritePSBinary(const uint8_t* data, int len) {
if (pEncoders &&
pEncoders->GetBasicModule()->A85Encode(data, len, &dest_buf,
&dest_size)) {
- m_pOutput->OutputPS((const char*)dest_buf, dest_size);
+ m_pStream->WriteBlock(dest_buf, dest_size);
FX_Free(dest_buf);
} else {
- m_pOutput->OutputPS((const char*)data, len);
+ m_pStream->WriteBlock(data, len);
}
}