Add print modes for PostScript level 3 + Type 42 fonts.
For use with FPDF_SetPrintMode(), in both regular and passthrough
varieties.
- Expose the new print modes via pdfium_test.
- Plumb print mode into CFX_PSRenderer.
Bug: chromium:1232526
Change-Id: I5099716c473eefe99738d9a5457fe3c41bd51bc8
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/84876
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fxge/cfx_windowsrenderdevice.h b/core/fxge/cfx_windowsrenderdevice.h
index 635c72b..8aa3ca3 100644
--- a/core/fxge/cfx_windowsrenderdevice.h
+++ b/core/fxge/cfx_windowsrenderdevice.h
@@ -19,6 +19,8 @@
kModePostScript2PassThrough = 4,
kModePostScript3PassThrough = 5,
kModeEmfImageMasks = 6,
+ kModePostScript3Type42 = 7,
+ kModePostScript3Type42PassThrough = 8,
};
struct EncoderIface;
diff --git a/core/fxge/win32/cfx_psrenderer.cpp b/core/fxge/win32/cfx_psrenderer.cpp
index e456989..f51ec05 100644
--- a/core/fxge/win32/cfx_psrenderer.cpp
+++ b/core/fxge/win32/cfx_psrenderer.cpp
@@ -57,10 +57,10 @@
CFX_PSRenderer::~CFX_PSRenderer() = default;
void CFX_PSRenderer::Init(const RetainPtr<IFX_RetainableWriteStream>& pStream,
- int pslevel,
+ RenderingLevel level,
int width,
int height) {
- m_PSLevel = pslevel;
+ m_Level = level;
m_pStream = pStream;
m_ClipBox.left = 0;
m_ClipBox.top = 0;
@@ -398,7 +398,7 @@
uint8_t* output_buf = nullptr;
size_t output_size = 0;
const char* filter = nullptr;
- if ((m_PSLevel == 2 || options.bLossy) &&
+ if ((m_Level.value() == RenderingLevel::kLevel2 || options.bLossy) &&
m_pEncoderIface->pJpegEncodeFunc(pConverted, &output_buf,
&output_size)) {
filter = "/DCTDecode filter ";
@@ -585,7 +585,7 @@
CFX_Font* font,
float font_size,
std::ostringstream& buf) {
- if (!CanEmbed(font))
+ if (m_Level != RenderingLevel::kLevel3Type42 || !CanEmbed(font))
return false;
if (font->GetFontType() != CFX_Font::FontType::kCIDTrueType)
@@ -664,7 +664,8 @@
uint8_t* dest_buf = nullptr;
uint32_t dest_size = src_size;
- if (m_PSLevel >= 3) {
+ if (m_Level.value() == RenderingLevel::kLevel3 ||
+ m_Level.value() == RenderingLevel::kLevel3Type42) {
std::unique_ptr<uint8_t, FxFreeDeleter> dest_buf_unique;
if (m_pEncoderIface->pFlateEncodeFunc(src_buf, src_size, &dest_buf_unique,
&dest_size)) {
diff --git a/core/fxge/win32/cfx_psrenderer.h b/core/fxge/win32/cfx_psrenderer.h
index 173e504..6716f7e 100644
--- a/core/fxge/win32/cfx_psrenderer.h
+++ b/core/fxge/win32/cfx_psrenderer.h
@@ -20,6 +20,7 @@
#include "core/fxcrt/retain_ptr.h"
#include "core/fxcrt/unowned_ptr.h"
#include "core/fxge/cfx_graphstatedata.h"
+#include "third_party/base/optional.h"
#include "third_party/base/span.h"
class CFX_DIBBase;
@@ -55,11 +56,17 @@
class CFX_PSRenderer {
public:
+ enum class RenderingLevel {
+ kLevel2,
+ kLevel3,
+ kLevel3Type42,
+ };
+
explicit CFX_PSRenderer(const EncoderIface* pEncoderIface);
~CFX_PSRenderer();
void Init(const RetainPtr<IFX_RetainableWriteStream>& stream,
- int pslevel,
+ RenderingLevel level,
int width,
int height);
void StartRendering();
@@ -139,7 +146,7 @@
bool m_bInited = false;
bool m_bGraphStateSet = false;
bool m_bColorSet = false;
- int m_PSLevel = 0;
+ Optional<RenderingLevel> m_Level;
uint32_t m_LastColor = 0;
FX_RECT m_ClipBox;
CFX_GraphStateData m_CurGraphState;
diff --git a/core/fxge/win32/cps_printer_driver.cpp b/core/fxge/win32/cps_printer_driver.cpp
index 6fbe528..efc65ff 100644
--- a/core/fxge/win32/cps_printer_driver.cpp
+++ b/core/fxge/win32/cps_printer_driver.cpp
@@ -19,22 +19,39 @@
#include "third_party/base/check.h"
#include "third_party/base/notreached.h"
+namespace {
+
+CFX_PSRenderer::RenderingLevel RenderingLevelFromWindowsPrintMode(
+ WindowsPrintMode mode) {
+ switch (mode) {
+ case WindowsPrintMode::kModePostScript2:
+ case WindowsPrintMode::kModePostScript2PassThrough:
+ return CFX_PSRenderer::RenderingLevel::kLevel2;
+ case WindowsPrintMode::kModePostScript3:
+ case WindowsPrintMode::kModePostScript3PassThrough:
+ return CFX_PSRenderer::RenderingLevel::kLevel3;
+ case WindowsPrintMode::kModePostScript3Type42:
+ case WindowsPrintMode::kModePostScript3Type42PassThrough:
+ return CFX_PSRenderer::RenderingLevel::kLevel3Type42;
+ default:
+ // |mode| should be PostScript.
+ NOTREACHED();
+ return CFX_PSRenderer::RenderingLevel::kLevel2;
+ }
+}
+
+} // namespace
+
CPSPrinterDriver::CPSPrinterDriver(HDC hDC,
WindowsPrintMode mode,
const EncoderIface* pEncoderIface)
: m_hDC(hDC), m_PSRenderer(pEncoderIface) {
- // |mode| should be PostScript.
- DCHECK(mode == WindowsPrintMode::kModePostScript2 ||
- mode == WindowsPrintMode::kModePostScript3 ||
- mode == WindowsPrintMode::kModePostScript2PassThrough ||
- mode == WindowsPrintMode::kModePostScript3PassThrough);
- int pslevel = (mode == WindowsPrintMode::kModePostScript2 ||
- mode == WindowsPrintMode::kModePostScript2PassThrough)
- ? 2
- : 3;
+ CFX_PSRenderer::RenderingLevel level =
+ RenderingLevelFromWindowsPrintMode(mode);
CPSOutput::OutputMode output_mode =
(mode == WindowsPrintMode::kModePostScript2 ||
- mode == WindowsPrintMode::kModePostScript3)
+ mode == WindowsPrintMode::kModePostScript3 ||
+ mode == WindowsPrintMode::kModePostScript3Type42)
? CPSOutput::OutputMode::kGdiComment
: CPSOutput::OutputMode::kExtEscape;
@@ -44,7 +61,7 @@
m_Height = ::GetDeviceCaps(m_hDC, VERTRES);
m_nBitsPerPixel = ::GetDeviceCaps(m_hDC, BITSPIXEL);
- m_PSRenderer.Init(pdfium::MakeRetain<CPSOutput>(m_hDC, output_mode), pslevel,
+ m_PSRenderer.Init(pdfium::MakeRetain<CPSOutput>(m_hDC, output_mode), level,
m_Width, m_Height);
HRGN hRgn = ::CreateRectRgn(0, 0, 1, 1);
if (::GetClipRgn(m_hDC, hRgn) == 1) {
diff --git a/fpdfsdk/fpdf_view.cpp b/fpdfsdk/fpdf_view.cpp
index 3e77099..998c127 100644
--- a/fpdfsdk/fpdf_view.cpp
+++ b/fpdfsdk/fpdf_view.cpp
@@ -83,6 +83,13 @@
static_assert(WindowsPrintMode::kModeEmfImageMasks ==
FPDF_PRINTMODE_EMF_IMAGE_MASKS,
"WindowsPrintMode::kModeEmfImageMasks value mismatch");
+static_assert(WindowsPrintMode::kModePostScript3Type42 ==
+ FPDF_PRINTMODE_POSTSCRIPT3_TYPE42,
+ "WindowsPrintMode::kModePostScript3Type42 value mismatch");
+static_assert(
+ WindowsPrintMode::kModePostScript3Type42PassThrough ==
+ FPDF_PRINTMODE_POSTSCRIPT3_TYPE42_PASSTHROUGH,
+ "WindowsPrintMode::kModePostScript3Type42PassThrough value mismatch");
#endif // defined(OS_WIN)
namespace {
@@ -219,8 +226,10 @@
#endif // PDFIUM_PRINT_TEXT_WITH_GDI
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SetPrintMode(int mode) {
- if (mode < FPDF_PRINTMODE_EMF || mode > FPDF_PRINTMODE_EMF_IMAGE_MASKS)
+ if (mode < FPDF_PRINTMODE_EMF ||
+ mode > FPDF_PRINTMODE_POSTSCRIPT3_TYPE42_PASSTHROUGH) {
return FALSE;
+ }
g_pdfium_print_mode = static_cast<WindowsPrintMode>(mode);
return TRUE;
diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h
index 40bb11f..294e7fb 100644
--- a/public/fpdf_edit.h
+++ b/public/fpdf_edit.h
@@ -71,6 +71,8 @@
#define FPDF_PRINTMODE_POSTSCRIPT2_PASSTHROUGH 4
#define FPDF_PRINTMODE_POSTSCRIPT3_PASSTHROUGH 5
#define FPDF_PRINTMODE_EMF_IMAGE_MASKS 6
+#define FPDF_PRINTMODE_POSTSCRIPT3_TYPE42 7
+#define FPDF_PRINTMODE_POSTSCRIPT3_TYPE42_PASSTHROUGH 8
typedef struct FPDF_IMAGEOBJ_METADATA {
// The image width in pixels.
diff --git a/public/fpdfview.h b/public/fpdfview.h
index 1cc7bd9..a3c22da 100644
--- a/public/fpdfview.h
+++ b/public/fpdfview.h
@@ -337,6 +337,12 @@
// PostScript via ExtEscape() in PASSTHROUGH mode.
// FPDF_PRINTMODE_EMF_IMAGE_MASKS to output EMF, with more
// efficient processing of documents containing image masks.
+// FPDF_PRINTMODE_POSTSCRIPT3_TYPE42 to output level 3
+// PostScript with embedded Type 42 fonts, when applicable, into
+// EMF as a series of GDI comments.
+// FPDF_PRINTMODE_POSTSCRIPT3_TYPE42_PASSTHROUGH to output level
+// 3 PostScript with embedded Type 42 fonts, when applicable,
+// via ExtEscape() in PASSTHROUGH mode.
// Return value:
// True if successful, false if unsuccessful (typically invalid input).
FPDF_EXPORT FPDF_BOOL FPDF_CALLCONV FPDF_SetPrintMode(int mode);
diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc
index 8f31b1d..4414a80 100644
--- a/samples/pdfium_test.cc
+++ b/samples/pdfium_test.cc
@@ -88,6 +88,7 @@
kEmf,
kPs2,
kPs3,
+ kPs3Type42,
#endif
#ifdef PDF_ENABLE_SKIA
kSkp,
@@ -565,6 +566,12 @@
return false;
}
options->output_format = OutputFormat::kPs3;
+ } else if (cur_arg == "--ps3-type42") {
+ if (options->output_format != OutputFormat::kNone) {
+ fprintf(stderr, "Duplicate or conflicting --ps3-type42 argument\n");
+ return false;
+ }
+ options->output_format = OutputFormat::kPs3Type42;
} else if (cur_arg == "--bmp") {
if (options->output_format != OutputFormat::kNone) {
fprintf(stderr, "Duplicate or conflicting --bmp argument\n");
@@ -1003,6 +1010,8 @@
FPDF_SetPrintMode(FPDF_PRINTMODE_POSTSCRIPT2);
else if (options.output_format == OutputFormat::kPs3)
FPDF_SetPrintMode(FPDF_PRINTMODE_POSTSCRIPT3);
+ else if (options.output_format == OutputFormat::kPs3Type42)
+ FPDF_SetPrintMode(FPDF_PRINTMODE_POSTSCRIPT3_TYPE42);
#endif
int page_count = FPDF_GetPageCount(doc.get());
@@ -1136,6 +1145,8 @@
"<pdf-name>.<page-number>.ps\n"
" --ps3 - write page raw PostScript (Lvl 3) "
"<pdf-name>.<page-number>.ps\n"
+ " --ps3-type42 - write page raw PostScript (Lvl 3 with Type 42 fonts) "
+ "<pdf-name>.<page-number>.ps\n"
#endif
" --txt - write page text in UTF32-LE <pdf-name>.<page-number>.txt\n"
" --png - write page images <pdf-name>.<page-number>.png\n"