summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorrbpotter <rbpotter@chromium.org>2017-07-11 10:04:29 -0700
committerChromium commit bot <commit-bot@chromium.org>2017-07-11 17:22:12 +0000
commite8468c43cb3b14f4440456d19cb047150509949d (patch)
treec11fc22bfe770abf5321fceb32644dca5c34faa1
parent00c3cfdbae074a379cab4edad0e4fa75d6127797 (diff)
downloadpdfium-e8468c43cb3b14f4440456d19cb047150509949d.tar.xz
Add Windows generic / text only printer driver support.
BUG=chromium:734850 Change-Id: Icc0947e2e99e77a36d8963fcf0b6d3deea161d3e Reviewed-on: https://pdfium-review.googlesource.com/7194 Commit-Queue: Rebekah Potter <rbpotter@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org>
-rw-r--r--core/fpdfapi/render/cpdf_charposlist.cpp3
-rw-r--r--core/fxge/cfx_renderdevice.cpp3
-rw-r--r--core/fxge/cfx_renderdevice.h1
-rw-r--r--core/fxge/cfx_windowsrenderdevice.h9
-rw-r--r--core/fxge/win32/fx_win32_device.cpp20
-rw-r--r--core/fxge/win32/fx_win32_print.cpp156
-rw-r--r--core/fxge/win32/win32_int.h62
-rw-r--r--fpdfsdk/fpdfview.cpp17
-rw-r--r--public/fpdf_edit.h5
-rw-r--r--public/fpdfview.h17
-rw-r--r--samples/pdfium_test.cc4
11 files changed, 274 insertions, 23 deletions
diff --git a/core/fpdfapi/render/cpdf_charposlist.cpp b/core/fpdfapi/render/cpdf_charposlist.cpp
index 68df46bdad..a87fc3334e 100644
--- a/core/fpdfapi/render/cpdf_charposlist.cpp
+++ b/core/fpdfapi/render/cpdf_charposlist.cpp
@@ -37,7 +37,8 @@ void CPDF_CharPosList::Load(const std::vector<uint32_t>& charCodes,
FXTEXT_CHARPOS& charpos = m_pCharPos[m_nChars++];
if (pCIDFont)
charpos.m_bFontStyle = true;
-
+ CFX_WideString unicode = pFont->UnicodeFromCharCode(CharCode);
+ charpos.m_Unicode = !unicode.IsEmpty() ? unicode.GetAt(0) : CharCode;
charpos.m_GlyphIndex = pFont->GlyphFromCharCode(CharCode, &bVert);
uint32_t GlyphID = charpos.m_GlyphIndex;
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
diff --git a/core/fxge/cfx_renderdevice.cpp b/core/fxge/cfx_renderdevice.cpp
index 266ae50e78..e1c6a65034 100644
--- a/core/fxge/cfx_renderdevice.cpp
+++ b/core/fxge/cfx_renderdevice.cpp
@@ -348,7 +348,8 @@ bool ShouldDrawDeviceText(const CFX_Font* pFont, uint32_t text_flags) {
} // namespace
FXTEXT_CHARPOS::FXTEXT_CHARPOS()
- : m_GlyphIndex(0),
+ : m_Unicode(0),
+ m_GlyphIndex(0),
m_FontCharWidth(0),
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
m_ExtGID(0),
diff --git a/core/fxge/cfx_renderdevice.h b/core/fxge/cfx_renderdevice.h
index f33da57cc9..165b729541 100644
--- a/core/fxge/cfx_renderdevice.h
+++ b/core/fxge/cfx_renderdevice.h
@@ -71,6 +71,7 @@ class FXTEXT_CHARPOS {
float m_AdjustMatrix[4];
CFX_PointF m_Origin;
+ uint32_t m_Unicode;
uint32_t m_GlyphIndex;
int32_t m_FontCharWidth;
#if _FXM_PLATFORM_ == _FXM_PLATFORM_APPLE_
diff --git a/core/fxge/cfx_windowsrenderdevice.h b/core/fxge/cfx_windowsrenderdevice.h
index 7156dcdc4e..f1e0cbdb7a 100644
--- a/core/fxge/cfx_windowsrenderdevice.h
+++ b/core/fxge/cfx_windowsrenderdevice.h
@@ -14,6 +14,13 @@
#include "core/fxge/cfx_renderdevice.h"
+enum WindowsPrintMode {
+ kModeEmf = 0,
+ kModeTextOnly = 1,
+ kModePostScript2 = 2,
+ kModePostScript3 = 3,
+};
+
class IFX_RenderDeviceDriver;
#if defined(PDFIUM_PRINT_TEXT_WITH_GDI)
@@ -25,7 +32,7 @@ extern bool g_pdfium_print_text_with_gdi;
extern PDFiumEnsureTypefaceCharactersAccessible
g_pdfium_typeface_accessible_func;
#endif
-extern int g_pdfium_print_postscript_level;
+extern int g_pdfium_print_mode;
class CFX_WindowsRenderDevice : public CFX_RenderDevice {
public:
diff --git a/core/fxge/win32/fx_win32_device.cpp b/core/fxge/win32/fx_win32_device.cpp
index ef3a7f2f8e..4427755cf5 100644
--- a/core/fxge/win32/fx_win32_device.cpp
+++ b/core/fxge/win32/fx_win32_device.cpp
@@ -689,7 +689,7 @@ bool CFX_Win32FontInfo::GetFontCharset(void* hFont, int* charset) {
} // namespace
-int g_pdfium_print_postscript_level = 0;
+int g_pdfium_print_mode = WindowsPrintMode::kModeEmf;
std::unique_ptr<IFX_SystemFontInfo> IFX_SystemFontInfo::CreateDefault(
const char** pUnused) {
@@ -1370,14 +1370,20 @@ IFX_RenderDeviceDriver* CFX_WindowsRenderDevice::CreateDriver(HDC hDC) {
int device_type = ::GetDeviceCaps(hDC, TECHNOLOGY);
int obj_type = ::GetObjectType(hDC);
bool use_printer = device_type == DT_RASPRINTER ||
- device_type == DT_PLOTTER || obj_type == OBJ_ENHMETADC;
+ device_type == DT_PLOTTER ||
+ device_type == DT_CHARSTREAM || obj_type == OBJ_ENHMETADC;
if (!use_printer)
return new CGdiDisplayDriver(hDC);
- if (g_pdfium_print_postscript_level == 2 ||
- g_pdfium_print_postscript_level == 3) {
- return new CPSPrinterDriver(hDC, g_pdfium_print_postscript_level, false);
- }
- return new CGdiPrinterDriver(hDC);
+ if (g_pdfium_print_mode == WindowsPrintMode::kModeEmf)
+ return new CGdiPrinterDriver(hDC);
+
+ if (g_pdfium_print_mode == WindowsPrintMode::kModeTextOnly)
+ return new CTextOnlyPrinterDriver(hDC);
+
+ // Should be PostScript
+ ASSERT(g_pdfium_print_mode == WindowsPrintMode::kModePostScript2 ||
+ g_pdfium_print_mode == WindowsPrintMode::kModePostScript3);
+ return new CPSPrinterDriver(hDC, g_pdfium_print_mode, false);
}
diff --git a/core/fxge/win32/fx_win32_print.cpp b/core/fxge/win32/fx_win32_print.cpp
index d7444f43a1..cae3859406 100644
--- a/core/fxge/win32/fx_win32_print.cpp
+++ b/core/fxge/win32/fx_win32_print.cpp
@@ -492,3 +492,159 @@ bool CPSPrinterDriver::DrawDeviceText(int nChars,
return m_PSRenderer.DrawText(nChars, pCharPos, pFont, pObject2Device,
font_size, color);
}
+
+CTextOnlyPrinterDriver::CTextOnlyPrinterDriver(HDC hDC)
+ : m_hDC(hDC),
+ m_Width(INT_MAX),
+ m_Height(INT_MAX),
+ m_HorzSize(INT_MAX),
+ m_VertSize(INT_MAX),
+ m_OriginY(0.0f),
+ m_SetOrigin(false) {
+ m_nBitsPerPixel = ::GetDeviceCaps(m_hDC, BITSPIXEL);
+}
+
+CTextOnlyPrinterDriver::~CTextOnlyPrinterDriver() {
+ EndRendering();
+}
+
+int CTextOnlyPrinterDriver::GetDeviceCaps(int caps_id) const {
+ switch (caps_id) {
+ case FXDC_DEVICE_CLASS:
+ return FXDC_PRINTER;
+ case FXDC_PIXEL_WIDTH:
+ return m_Width;
+ case FXDC_PIXEL_HEIGHT:
+ return m_Height;
+ case FXDC_BITS_PIXEL:
+ return m_nBitsPerPixel;
+ case FXDC_RENDER_CAPS:
+ return 0;
+ case FXDC_HORZ_SIZE:
+ return m_HorzSize;
+ case FXDC_VERT_SIZE:
+ return m_VertSize;
+ }
+ return 0;
+}
+
+bool CTextOnlyPrinterDriver::SetClip_PathFill(const CFX_PathData* pPathData,
+ const CFX_Matrix* pObject2Device,
+ int fill_mode) {
+ return true;
+}
+
+bool CTextOnlyPrinterDriver::SetClip_PathStroke(
+ const CFX_PathData* pPathData,
+ const CFX_Matrix* pObject2Device,
+ const CFX_GraphStateData* pGraphState) {
+ return false;
+}
+
+bool CTextOnlyPrinterDriver::DrawPath(const CFX_PathData* pPathData,
+ const CFX_Matrix* pObject2Device,
+ const CFX_GraphStateData* pGraphState,
+ uint32_t fill_color,
+ uint32_t stroke_color,
+ int fill_mode,
+ int blend_type) {
+ return false;
+}
+
+bool CTextOnlyPrinterDriver::SetDIBits(
+ const CFX_RetainPtr<CFX_DIBSource>& pBitmap,
+ uint32_t color,
+ const FX_RECT* pSrcRect,
+ int left,
+ int top,
+ int blend_type) {
+ return false;
+}
+
+bool CTextOnlyPrinterDriver::GetClipBox(FX_RECT* pRect) {
+ pRect->left = 0;
+ pRect->right = m_Width;
+ pRect->top = 0;
+ pRect->bottom = m_Height;
+ return true;
+}
+
+bool CTextOnlyPrinterDriver::StretchDIBits(
+ const CFX_RetainPtr<CFX_DIBSource>& pBitmap,
+ uint32_t color,
+ int dest_left,
+ int dest_top,
+ int dest_width,
+ int dest_height,
+ const FX_RECT* pClipRect,
+ uint32_t flags,
+ int blend_type) {
+ return false;
+}
+
+bool CTextOnlyPrinterDriver::StartDIBits(
+ const CFX_RetainPtr<CFX_DIBSource>& pBitmap,
+ int bitmap_alpha,
+ uint32_t color,
+ const CFX_Matrix* pMatrix,
+ uint32_t render_flags,
+ std::unique_ptr<CFX_ImageRenderer>* handle,
+ int blend_type) {
+ return false;
+}
+
+bool CTextOnlyPrinterDriver::DrawDeviceText(int nChars,
+ const FXTEXT_CHARPOS* pCharPos,
+ CFX_Font* pFont,
+ const CFX_Matrix* pObject2Device,
+ float font_size,
+ uint32_t color) {
+ if (g_pdfium_print_mode != 1)
+ return false;
+ if (nChars < 1 || !pFont || !pFont->IsEmbedded() || !pFont->IsTTFont())
+ return false;
+
+ // Scale factor used to minimize the kerning problems caused by rounding
+ // errors below. Value chosen based on the title of https://crbug.com/18383
+ const double kScaleFactor = 10;
+
+ CFX_WideString wsText;
+ int totalLength = nChars;
+
+ // Detect new lines and add a space. Was likely removed by SkPDF if this is
+ // just text, and spaces seem to be ignored by label printers that use this
+ // driver.
+ if (m_SetOrigin &&
+ FXSYS_round(m_OriginY) != FXSYS_round(pObject2Device->f * kScaleFactor)) {
+ wsText += L" ";
+ totalLength++;
+ }
+ m_OriginY = pObject2Device->f * kScaleFactor;
+ m_SetOrigin = true;
+
+ // Text
+ for (int i = 0; i < nChars; ++i) {
+ // Only works with PDFs from Skia's PDF generator. Cannot handle arbitrary
+ // values from PDFs.
+ const FXTEXT_CHARPOS& charpos = pCharPos[i];
+ ASSERT(charpos.m_AdjustMatrix[0] == 0);
+ ASSERT(charpos.m_AdjustMatrix[1] == 0);
+ ASSERT(charpos.m_AdjustMatrix[2] == 0);
+ ASSERT(charpos.m_AdjustMatrix[3] == 0);
+ ASSERT(charpos.m_Origin.y == 0);
+
+ wsText += charpos.m_Unicode;
+ }
+ size_t len = totalLength;
+ CFX_ByteString text = CFX_ByteString::FromUnicode(wsText);
+ while (len > 0) {
+ char buffer[1026];
+ size_t send_len = std::min(len, static_cast<size_t>(1024));
+ *(reinterpret_cast<uint16_t*>(buffer)) = send_len;
+ memcpy(buffer + 2, text.c_str(), send_len);
+ ::GdiComment(m_hDC, send_len + 2, reinterpret_cast<const BYTE*>(buffer));
+ len -= send_len;
+ text.Right(len);
+ }
+ return true;
+}
diff --git a/core/fxge/win32/win32_int.h b/core/fxge/win32/win32_int.h
index d92d3b333c..c51bae7f67 100644
--- a/core/fxge/win32/win32_int.h
+++ b/core/fxge/win32/win32_int.h
@@ -333,4 +333,66 @@ class CPSPrinterDriver : public IFX_RenderDeviceDriver {
CFX_PSRenderer m_PSRenderer;
};
+class CTextOnlyPrinterDriver : public IFX_RenderDeviceDriver {
+ public:
+ explicit CTextOnlyPrinterDriver(HDC hDC);
+ ~CTextOnlyPrinterDriver() override;
+
+ protected:
+ // IFX_RenderDeviceDriver
+ int GetDeviceCaps(int caps_id) const override;
+ void SaveState() override{};
+ void RestoreState(bool bKeepSaved) override{};
+ bool SetClip_PathFill(const CFX_PathData* pPathData,
+ const CFX_Matrix* pObject2Device,
+ int fill_mode) override;
+ bool SetClip_PathStroke(const CFX_PathData* pPathData,
+ const CFX_Matrix* pObject2Device,
+ const CFX_GraphStateData* pGraphState) override;
+ bool DrawPath(const CFX_PathData* pPathData,
+ const CFX_Matrix* pObject2Device,
+ const CFX_GraphStateData* pGraphState,
+ uint32_t fill_color,
+ uint32_t stroke_color,
+ int fill_mode,
+ int blend_type) override;
+ bool GetClipBox(FX_RECT* pRect) override;
+ bool SetDIBits(const CFX_RetainPtr<CFX_DIBSource>& pBitmap,
+ uint32_t color,
+ const FX_RECT* pSrcRect,
+ int left,
+ int top,
+ int blend_type) override;
+ bool StretchDIBits(const CFX_RetainPtr<CFX_DIBSource>& pBitmap,
+ uint32_t color,
+ int dest_left,
+ int dest_top,
+ int dest_width,
+ int dest_height,
+ const FX_RECT* pClipRect,
+ uint32_t flags,
+ int blend_type) override;
+ bool StartDIBits(const CFX_RetainPtr<CFX_DIBSource>& pBitmap,
+ int bitmap_alpha,
+ uint32_t color,
+ const CFX_Matrix* pMatrix,
+ uint32_t render_flags,
+ std::unique_ptr<CFX_ImageRenderer>* handle,
+ int blend_type) override;
+ bool DrawDeviceText(int nChars,
+ const FXTEXT_CHARPOS* pCharPos,
+ CFX_Font* pFont,
+ const CFX_Matrix* pObject2Device,
+ float font_size,
+ uint32_t color) override;
+
+ HDC m_hDC;
+ int m_Width;
+ int m_Height;
+ int m_nBitsPerPixel;
+ int m_HorzSize;
+ int m_VertSize;
+ float m_OriginY;
+ bool m_SetOrigin;
+};
#endif // CORE_FXGE_WIN32_WIN32_INT_H_
diff --git a/fpdfsdk/fpdfview.cpp b/fpdfsdk/fpdfview.cpp
index 1c282a744d..4d0845b616 100644
--- a/fpdfsdk/fpdfview.cpp
+++ b/fpdfsdk/fpdfview.cpp
@@ -37,6 +37,7 @@
#include "fpdfsdk/fsdk_define.h"
#include "fpdfsdk/fsdk_pauseadapter.h"
#include "fpdfsdk/javascript/ijs_runtime.h"
+#include "public/fpdf_edit.h"
#include "public/fpdf_ext.h"
#include "public/fpdf_progressive.h"
#include "third_party/base/allocator/partition_allocator/partition_alloc.h"
@@ -53,6 +54,16 @@
#if _FXM_PLATFORM_ == _FXM_PLATFORM_WINDOWS_
#include "core/fxge/cfx_windowsrenderdevice.h"
+
+// These checks are here because core/ and public/ cannot depend on each other.
+static_assert(WindowsPrintMode::kModeEmf == FPDF_PRINTMODE_EMF,
+ "WindowsPrintMode::kModeEmf value mismatch");
+static_assert(WindowsPrintMode::kModeTextOnly == FPDF_PRINTMODE_TEXTONLY,
+ "WindowsPrintMode::kModeTextOnly value mismatch");
+static_assert(WindowsPrintMode::kModePostScript2 == FPDF_PRINTMODE_POSTSCRIPT2,
+ "WindowsPrintMode::kModePostScript2 value mismatch");
+static_assert(WindowsPrintMode::kModePostScript3 == FPDF_PRINTMODE_POSTSCRIPT3,
+ "WindowsPrintMode::kModePostScript3 value mismatch");
#endif
namespace {
@@ -449,10 +460,10 @@ DLLEXPORT void STDCALL FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi) {
}
#endif // PDFIUM_PRINT_TEXT_WITH_GDI
-DLLEXPORT FPDF_BOOL STDCALL FPDF_SetPrintPostscriptLevel(int postscript_level) {
- if (postscript_level != 0 && postscript_level != 2 && postscript_level != 3)
+DLLEXPORT FPDF_BOOL STDCALL FPDF_SetPrintMode(int mode) {
+ if (mode < FPDF_PRINTMODE_EMF || mode > FPDF_PRINTMODE_POSTSCRIPT3)
return FALSE;
- g_pdfium_print_postscript_level = postscript_level;
+ g_pdfium_print_mode = mode;
return TRUE;
}
#endif // defined(_WIN32)
diff --git a/public/fpdf_edit.h b/public/fpdf_edit.h
index 4d5826ddbc..aa221fec34 100644
--- a/public/fpdf_edit.h
+++ b/public/fpdf_edit.h
@@ -42,6 +42,11 @@
#define FPDF_LINEJOIN_ROUND 1
#define FPDF_LINEJOIN_BEVEL 2
+#define FPDF_PRINTMODE_EMF 0
+#define FPDF_PRINTMODE_TEXTONLY 1
+#define FPDF_PRINTMODE_POSTSCRIPT2 2
+#define FPDF_PRINTMODE_POSTSCRIPT3 3
+
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
diff --git a/public/fpdfview.h b/public/fpdfview.h
index 1ff0aeb267..df46e9700b 100644
--- a/public/fpdfview.h
+++ b/public/fpdfview.h
@@ -245,17 +245,18 @@ FPDF_SetTypefaceAccessibleFunc(PDFiumEnsureTypefaceCharactersAccessible func);
DLLEXPORT void STDCALL FPDF_SetPrintTextWithGDI(FPDF_BOOL use_gdi);
#endif // PDFIUM_PRINT_TEXT_WITH_GDI
-// Function: FPDF_SetPrintPostscriptLevel
-// Set postscript printing level when printing on Windows.
+// Function: FPDF_SetPrintMode
+// Set printing mode when printing on Windows.
// Experimental API.
// Parameters:
-// postscript_level - 0 to disable postscript printing,
-// 2 to print with postscript level 2,
-// 3 to print with postscript level 3.
-// All other values are invalid.
+// mode - FPDF_PRINTMODE_EMF to output EMF (default)
+// FPDF_PRINTMODE_TEXTONLY to output text only (for charstream
+// devices)
+// FPDF_PRINTMODE_POSTSCRIPT2 to output level 2 postscript
+// FPDF_PRINTMODE_POSTSCRIPT3 to output level 3 postscript
// Return value:
-// True if successful, false if unsucessful (typically invalid input).
-DLLEXPORT FPDF_BOOL STDCALL FPDF_SetPrintPostscriptLevel(int postscript_level);
+// True if successful, false if unsuccessful (typically invalid input).
+DLLEXPORT FPDF_BOOL STDCALL FPDF_SetPrintMode(int mode);
#endif // defined(_WIN32)
// Function: FPDF_LoadDocument
diff --git a/samples/pdfium_test.cc b/samples/pdfium_test.cc
index 5eccf22554..85cc0d3526 100644
--- a/samples/pdfium_test.cc
+++ b/samples/pdfium_test.cc
@@ -1137,9 +1137,9 @@ void RenderPdf(const std::string& name,
#if _WIN32
if (options.output_format == OUTPUT_PS2)
- FPDF_SetPrintPostscriptLevel(2);
+ FPDF_SetPrintMode(2);
else if (options.output_format == OUTPUT_PS3)
- FPDF_SetPrintPostscriptLevel(3);
+ FPDF_SetPrintMode(3);
#endif
int page_count = FPDF_GetPageCount(doc.get());