summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authordan sinclair <dsinclair@chromium.org>2017-05-12 21:22:08 -0400
committerChromium commit bot <commit-bot@chromium.org>2017-05-15 15:40:43 +0000
commitd2afac1e9200478997e308eecc582a073185d7ab (patch)
tree1ec1a2c69168cb2ab3f1418fae0e9f1c754cebdb
parent017ebba6940e0fe5ff39122c033600f88f24539a (diff)
downloadpdfium-d2afac1e9200478997e308eecc582a073185d7ab.tar.xz
Convert CPSOutput to an IFX_WriteStream
This Cl updates CPSOutput to inherit from IFX_WriteStream and converts the CFX_PSRenderer to accept an IFX_WriteStream instead of a CPSOutput. Change-Id: Ibde5c7da1c2f6df0a10cb6e9a470e18fbab167b8 Reviewed-on: https://pdfium-review.googlesource.com/5431 Reviewed-by: Nicolás Peña <npm@chromium.org> Commit-Queue: dsinclair <dsinclair@chromium.org>
-rw-r--r--core/fxge/win32/cfx_psrenderer.cpp274
-rw-r--r--core/fxge/win32/cfx_psrenderer.h7
-rw-r--r--core/fxge/win32/cpsoutput.cpp22
-rw-r--r--core/fxge/win32/cpsoutput.h12
-rw-r--r--core/fxge/win32/fx_win32_print.cpp5
-rw-r--r--core/fxge/win32/win32_int.h2
6 files changed, 165 insertions, 157 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);
}
}
diff --git a/core/fxge/win32/cfx_psrenderer.h b/core/fxge/win32/cfx_psrenderer.h
index 5768d0770f..01a9001b62 100644
--- a/core/fxge/win32/cfx_psrenderer.h
+++ b/core/fxge/win32/cfx_psrenderer.h
@@ -10,10 +10,11 @@
#include <memory>
#include <vector>
+#include "core/fxcrt/cfx_retain_ptr.h"
#include "core/fxcrt/fx_coordinates.h"
+#include "core/fxcrt/fx_stream.h"
#include "core/fxcrt/fx_system.h"
#include "core/fxge/cfx_graphstatedata.h"
-#include "core/fxge/win32/cpsoutput.h"
class CFX_DIBSource;
class CFX_FaceCache;
@@ -29,7 +30,7 @@ class CFX_PSRenderer {
CFX_PSRenderer();
~CFX_PSRenderer();
- void Init(CPSOutput* pOutput,
+ void Init(const CFX_RetainPtr<IFX_WriteStream>& stream,
int pslevel,
int width,
int height,
@@ -85,7 +86,7 @@ class CFX_PSRenderer {
int* ps_glyphindex);
void WritePSBinary(const uint8_t* data, int len);
- CPSOutput* m_pOutput;
+ CFX_RetainPtr<IFX_WriteStream> m_pStream;
int m_PSLevel;
CFX_GraphStateData m_CurGraphState;
bool m_bGraphStateSet;
diff --git a/core/fxge/win32/cpsoutput.cpp b/core/fxge/win32/cpsoutput.cpp
index 7a8434ec33..7139340a6e 100644
--- a/core/fxge/win32/cpsoutput.cpp
+++ b/core/fxge/win32/cpsoutput.cpp
@@ -10,26 +10,17 @@
#include "core/fxcrt/fx_system.h"
-CPSOutput::CPSOutput(HDC hDC) {
- m_hDC = hDC;
-}
+CPSOutput::CPSOutput(HDC hDC) : m_hDC(hDC) {}
CPSOutput::~CPSOutput() {}
-void CPSOutput::Release() {
- delete this;
-}
-
-void CPSOutput::OutputPS(const char* str, int len) {
- if (len < 0)
- len = static_cast<int>(FXSYS_strlen(str));
-
+bool CPSOutput::WriteBlock(const void* str, size_t len) {
int sent_len = 0;
while (len > 0) {
char buffer[1026];
- int send_len = std::min(len, 1024);
+ size_t send_len = std::min(len, static_cast<size_t>(1024));
*(reinterpret_cast<uint16_t*>(buffer)) = send_len;
- memcpy(buffer + 2, str + sent_len, send_len);
+ memcpy(buffer + 2, static_cast<const char*>(str) + sent_len, send_len);
// TODO(thestig/rbpotter): Do PASSTHROUGH for non-Chromium usage.
// ExtEscape(m_hDC, PASSTHROUGH, send_len + 2, buffer, 0, nullptr);
@@ -37,4 +28,9 @@ void CPSOutput::OutputPS(const char* str, int len) {
sent_len += send_len;
len -= send_len;
}
+ return true;
+}
+
+bool CPSOutput::WriteString(const CFX_ByteStringC& str) {
+ return WriteBlock(str.c_str(), str.GetLength());
}
diff --git a/core/fxge/win32/cpsoutput.h b/core/fxge/win32/cpsoutput.h
index 1a4709b36b..42ad109a80 100644
--- a/core/fxge/win32/cpsoutput.h
+++ b/core/fxge/win32/cpsoutput.h
@@ -9,17 +9,19 @@
#include <windows.h>
+#include "core/fxcrt/fx_stream.h"
#include "core/fxcrt/fx_system.h"
-class CPSOutput {
+class CPSOutput : public IFX_WriteStream {
public:
explicit CPSOutput(HDC hDC);
- ~CPSOutput();
+ ~CPSOutput() override;
- // IFX_PSOutput
- void Release();
- void OutputPS(const char* str, int len);
+ // IFX_Writestream
+ bool WriteBlock(const void* str, size_t len) override;
+ bool WriteString(const CFX_ByteStringC& str) override;
+ private:
HDC m_hDC;
};
diff --git a/core/fxge/win32/fx_win32_print.cpp b/core/fxge/win32/fx_win32_print.cpp
index e036a8c97d..8f7cbf5be0 100644
--- a/core/fxge/win32/fx_win32_print.cpp
+++ b/core/fxge/win32/fx_win32_print.cpp
@@ -337,8 +337,9 @@ CPSPrinterDriver::CPSPrinterDriver(HDC hDC, int pslevel, bool bCmykOutput)
m_Width = ::GetDeviceCaps(m_hDC, HORZRES);
m_Height = ::GetDeviceCaps(m_hDC, VERTRES);
m_nBitsPerPixel = ::GetDeviceCaps(m_hDC, BITSPIXEL);
- m_pPSOutput = pdfium::MakeUnique<CPSOutput>(m_hDC);
- m_PSRenderer.Init(m_pPSOutput.get(), pslevel, m_Width, m_Height, bCmykOutput);
+
+ m_PSRenderer.Init(pdfium::MakeRetain<CPSOutput>(m_hDC), pslevel, m_Width,
+ m_Height, bCmykOutput);
HRGN hRgn = ::CreateRectRgn(0, 0, 1, 1);
int ret = ::GetClipRgn(hDC, hRgn);
if (ret == 1) {
diff --git a/core/fxge/win32/win32_int.h b/core/fxge/win32/win32_int.h
index 2f69c0ea57..d92d3b333c 100644
--- a/core/fxge/win32/win32_int.h
+++ b/core/fxge/win32/win32_int.h
@@ -11,6 +11,7 @@
#include <memory>
+#include "core/fxcrt/cfx_retain_ptr.h"
#include "core/fxge/cfx_pathdata.h"
#include "core/fxge/ifx_renderdevicedriver.h"
#include "core/fxge/win32/cfx_psrenderer.h"
@@ -329,7 +330,6 @@ class CPSPrinterDriver : public IFX_RenderDeviceDriver {
int m_nBitsPerPixel;
int m_HorzSize;
int m_VertSize;
- std::unique_ptr<CPSOutput> m_pPSOutput;
CFX_PSRenderer m_PSRenderer;
};