diff options
author | rbpotter <rbpotter@chromium.org> | 2017-01-12 10:31:43 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2017-01-12 10:31:43 -0800 |
commit | db7647083d0a5cd2221b94faa15c149214d21725 (patch) | |
tree | 427c0beeb82796e8e550e672195061186d7db076 /core | |
parent | e7fb8eb3e9f220a5f0c852f0238ab8d536a8bc9d (diff) | |
download | pdfium-db7647083d0a5cd2221b94faa15c149214d21725.tar.xz |
Add postscript path
This patch adds the additional functions required to make postscript
printing functional. The most significant additions are are two added
compression functions and a new API for setting the postscript level.
Not currently called from Chromium, Chromium patch to come.
BUG=
Review-Url: https://codereview.chromium.org/2612243005
Diffstat (limited to 'core')
-rw-r--r-- | core/fxcodec/codec/fx_codec.cpp | 142 | ||||
-rw-r--r-- | core/fxcodec/codec/fx_codec_a85_unittest.cpp | 209 | ||||
-rw-r--r-- | core/fxcodec/codec/fx_codec_rle_unittest.cpp | 195 | ||||
-rw-r--r-- | core/fxge/cfx_windowsdevice.h | 1 | ||||
-rw-r--r-- | core/fxge/win32/cfx_psrenderer.cpp | 78 | ||||
-rw-r--r-- | core/fxge/win32/fx_win32_device.cpp | 18 | ||||
-rw-r--r-- | core/fxge/win32/fx_win32_print.cpp | 9 |
7 files changed, 596 insertions, 56 deletions
diff --git a/core/fxcodec/codec/fx_codec.cpp b/core/fxcodec/codec/fx_codec.cpp index 6b6c723388..23171cf3ea 100644 --- a/core/fxcodec/codec/fx_codec.cpp +++ b/core/fxcodec/codec/fx_codec.cpp @@ -6,6 +6,7 @@ #include "core/fxcodec/fx_codec.h" +#include <algorithm> #include <cmath> #include <memory> #include <utility> @@ -101,14 +102,151 @@ bool CCodec_BasicModule::RunLengthEncode(const uint8_t* src_buf, uint32_t src_size, uint8_t** dest_buf, uint32_t* dest_size) { - return false; + // Check inputs + if (!src_buf || !dest_buf || !dest_size || src_size == 0) + return false; + + // Edge case + if (src_size == 1) { + *dest_buf = FX_Alloc(uint8_t, 3); + (*dest_buf)[0] = 0; + (*dest_buf)[1] = src_buf[0]; + (*dest_buf)[2] = 128; + *dest_size = 3; + return true; + } + + // Worst case: 1 nonmatch, 2 match, 1 nonmatch, 2 match, etc. This becomes + // 4 output chars for every 3 input, plus up to 4 more for the 1-2 chars + // rounded off plus the terminating character. + uint32_t est_size = 4 * ((src_size + 2) / 3) + 1; + *dest_buf = FX_Alloc(uint8_t, est_size); + + // Set up pointers. + uint8_t* out = *dest_buf; + uint32_t run_start = 0; + uint32_t run_end = 1; + uint8_t x = src_buf[run_start]; + uint8_t y = src_buf[run_end]; + while (run_end < src_size) { + uint32_t max_len = std::min((uint32_t)128, src_size - run_start); + while (x == y && (run_end - run_start < max_len - 1)) + y = src_buf[++run_end]; + + // Reached end with matched run. Update variables to expected values. + if (x == y) { + run_end++; + if (run_end < src_size) + y = src_buf[run_end]; + } + if (run_end - run_start > 1) { // Matched run but not at end of input. + out[0] = 257 - (run_end - run_start); + out[1] = x; + x = y; + run_start = run_end; + run_end++; + if (run_end < src_size) + y = src_buf[run_end]; + out += 2; + continue; + } + // Mismatched run + while (x != y && run_end <= run_start + max_len) { + out[run_end - run_start] = x; + x = y; + run_end++; + if (run_end == src_size) { + if (run_end <= run_start + max_len) { + out[run_end - run_start] = x; + run_end++; + } + break; + } + y = src_buf[run_end]; + } + out[0] = run_end - run_start - 2; + out += run_end - run_start; + run_start = run_end - 1; + } + if (run_start < src_size) { // 1 leftover character + out[0] = 0; + out[1] = x; + out += 2; + } + *out = 128; + *dest_size = out + 1 - *dest_buf; + return true; } bool CCodec_BasicModule::A85Encode(const uint8_t* src_buf, uint32_t src_size, uint8_t** dest_buf, uint32_t* dest_size) { - return false; + // Check inputs. + if (!src_buf || !dest_buf || !dest_size) + return false; + + if (src_size == 0) { + *dest_size = 0; + return false; + } + + // Worst case: 5 output for each 4 input (plus up to 4 from leftover), plus + // 2 character new lines each 75 output chars plus 2 termination chars. May + // have fewer if there are special "z" chars. + uint32_t est_size = 5 * (src_size / 4) + 4 + src_size / 30 + 2; + *dest_buf = FX_Alloc(uint8_t, est_size); + + // Set up pointers. + uint8_t* out = *dest_buf; + uint32_t pos = 0; + uint32_t line_length = 0; + while (src_size >= 4 && pos < src_size - 3) { + uint32_t val = ((uint32_t)(src_buf[pos]) << 24) + + ((uint32_t)(src_buf[pos + 1]) << 16) + + ((uint32_t)(src_buf[pos + 2]) << 8) + + (uint32_t)(src_buf[pos + 3]); + pos += 4; + if (val == 0) { // All zero special case + *out = 'z'; + out++; + line_length++; + } else { // Compute base 85 characters and add 33. + for (int i = 4; i >= 0; i--) { + out[i] = (uint8_t)(val % 85) + 33; + val = val / 85; + } + out += 5; + line_length += 5; + } + if (line_length >= 75) { // Add a return. + *out++ = '\r'; + *out++ = '\n'; + line_length = 0; + } + } + if (pos < src_size) { // Leftover bytes + uint32_t val = 0; + int count = 0; + while (pos < src_size) { + val += (uint32_t)(src_buf[pos] << (8 * (3 - pos))); + count++; + pos++; + } + for (int i = 4; i >= 0; i--) { + if (i <= count) + out[i] = (uint8_t)(val % 85) + 33; + val = val / 85; + } + out += count + 1; + } + + // Terminating characters. + out[0] = '~'; + out[1] = '>'; + out += 2; + *dest_size = out - *dest_buf; + return true; } #ifdef PDF_ENABLE_XFA diff --git a/core/fxcodec/codec/fx_codec_a85_unittest.cpp b/core/fxcodec/codec/fx_codec_a85_unittest.cpp new file mode 100644 index 0000000000..7910881772 --- /dev/null +++ b/core/fxcodec/codec/fx_codec_a85_unittest.cpp @@ -0,0 +1,209 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stdint.h> + +#include <limits> + +#include "core/fxcodec/codec/ccodec_basicmodule.h" +#include "core/fxcodec/fx_codec.h" +#include "testing/fx_string_testhelpers.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(fxcodec, A85TestBadInputs) { + uint8_t src_buf[4] = {1, 2, 3, 4}; + uint8_t* dest_buf = nullptr; + uint32_t src_size = 4; + uint32_t dest_size = 0; + + CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); + EXPECT_TRUE(pEncoders); + + // Error codes, not segvs, should callers pass us a nullptr pointer. + EXPECT_FALSE(pEncoders->A85Encode(src_buf, src_size, &dest_buf, nullptr)); + EXPECT_FALSE(pEncoders->A85Encode(src_buf, src_size, nullptr, &dest_size)); + EXPECT_FALSE(pEncoders->A85Encode(src_buf, 0, &dest_buf, &dest_size)); + EXPECT_FALSE(pEncoders->A85Encode(nullptr, src_size, &dest_buf, &dest_size)); +} + +// No leftover bytes, just translate 2 sets of symbols. +TEST(fxcodec, A85TestBasic) { + // Make sure really big values don't break. + uint8_t src_buf[8] = {1, 2, 3, 4, 255, 255, 255, 255}; + uint8_t* dest_buf = nullptr; + uint32_t src_size = 8; + uint32_t dest_size = 0; + + CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); + EXPECT_TRUE(pEncoders); + + // Should succeed. + EXPECT_TRUE(pEncoders->A85Encode(src_buf, src_size, &dest_buf, &dest_size)); + + // Should have 5 chars for each set of 4 and 2 terminators. + EXPECT_EQ(12u, dest_size); + uint8_t expected_out[12] = {33, 60, 78, 63, 43, 115, 56, 87, 45, 33, 126, 62}; + + // Check the output + for (uint32_t i = 0; i < 12; i++) + EXPECT_EQ(dest_buf[i], expected_out[i]) << " at " << i; + FX_Free(dest_buf); +} + +// Leftover bytes. +TEST(fxcodec, A85TestLeftoverBytes) { + // 1 Leftover Byte: + uint8_t src_buf_1leftover[5] = {1, 2, 3, 4, 255}; + uint8_t* dest_buf = nullptr; + uint32_t src_size = 5; + uint32_t dest_size = 0; + + CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); + EXPECT_TRUE(pEncoders); + + // Should succeed + EXPECT_TRUE( + pEncoders->A85Encode(src_buf_1leftover, src_size, &dest_buf, &dest_size)); + EXPECT_EQ(9u, dest_size); // 5 chars for first symbol + 2 + 2 terminators. + uint8_t expected_out_1leftover[9] = {33, 60, 78, 63, 43, 114, 114, 126, 62}; + + // Check the output + for (uint32_t i = 0; i < 9; i++) + EXPECT_EQ(dest_buf[i], expected_out_1leftover[i]) << " at " << i; + FX_Free(dest_buf); + + // 2 Leftover bytes: + src_size++; + dest_buf = nullptr; + dest_size = 0; + uint8_t src_buf_2leftover[6] = {1, 2, 3, 4, 255, 254}; + // Should succeed + EXPECT_TRUE( + pEncoders->A85Encode(src_buf_2leftover, src_size, &dest_buf, &dest_size)); + EXPECT_EQ(10u, dest_size); // 5 chars for first symbol + 3 + 2 terminators. + uint8_t expected_out_2leftover[10] = {33, 60, 78, 63, 43, + 115, 56, 68, 126, 62}; + + // Check the output + for (uint32_t i = 0; i < 10; i++) + EXPECT_EQ(dest_buf[i], expected_out_2leftover[i]) << " at " << i; + FX_Free(dest_buf); + + // 3 Leftover bytes: + src_size++; + dest_buf = nullptr; + dest_size = 0; + uint8_t src_buf_3leftover[7] = {1, 2, 3, 4, 255, 254, 253}; + // Should succeed + EXPECT_TRUE( + pEncoders->A85Encode(src_buf_3leftover, src_size, &dest_buf, &dest_size)); + EXPECT_EQ(11u, dest_size); // 5 chars for first symbol + 4 + 2 terminators. + uint8_t expected_out_3leftover[11] = {33, 60, 78, 63, 43, 115, + 56, 77, 114, 126, 62}; + + // Check the output + for (uint32_t i = 0; i < 11; i++) + EXPECT_EQ(dest_buf[i], expected_out_3leftover[i]) << " at " << i; + FX_Free(dest_buf); +} + +// Test all zeros comes through as "z". +TEST(fxcodec, A85TestZeros) { + // Make sure really big values don't break. + uint8_t src_buf[8] = {1, 2, 3, 4, 0, 0, 0, 0}; + uint8_t* dest_buf = nullptr; + uint32_t src_size = 8; + uint32_t dest_size = 0; + + CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); + EXPECT_TRUE(pEncoders); + + // Should succeed. + EXPECT_TRUE(pEncoders->A85Encode(src_buf, src_size, &dest_buf, &dest_size)); + + // Should have 5 chars for first set of 4 + 1 for z + 2 terminators. + EXPECT_EQ(8u, dest_size); + uint8_t expected_out[8] = {33, 60, 78, 63, 43, 122, 126, 62}; + + // Check the output + for (uint32_t i = 0; i < 8; i++) + EXPECT_EQ(dest_buf[i], expected_out[i]) << " at " << i; + FX_Free(dest_buf); + + // Should also work if it is at the start: + dest_buf = nullptr; + dest_size = 0; + uint8_t src_buf_2[8] = {0, 0, 0, 0, 1, 2, 3, 4}; + + // Should succeed. + EXPECT_TRUE(pEncoders->A85Encode(src_buf_2, src_size, &dest_buf, &dest_size)); + + // Should have 5 chars for set of 4 + 1 for z + 2 terminators. + EXPECT_EQ(8u, dest_size); + uint8_t expected_out_2[8] = {122, 33, 60, 78, 63, 43, 126, 62}; + + // Check the output + for (uint32_t i = 0; i < 8; i++) + EXPECT_EQ(dest_buf[i], expected_out_2[i]) << " at " << i; + FX_Free(dest_buf); + + // Try with 2 leftover zero bytes. Make sure we don't get a "z". + src_size = 6; // Cut off the last 2 zeros. + dest_buf = nullptr; + dest_size = 0; + + // Should succeed. + EXPECT_TRUE(pEncoders->A85Encode(src_buf, src_size, &dest_buf, &dest_size)); + + // Should have 5 chars for set of 4 + 3 for last 2 + 2 terminators. + EXPECT_EQ(10u, dest_size); + uint8_t expected_out_leftover[10] = {33, 60, 78, 63, 43, 33, 33, 33, 126, 62}; + + // Check the output + for (uint32_t i = 0; i < 10; i++) + EXPECT_EQ(dest_buf[i], expected_out_leftover[i]) << " at " << i; + FX_Free(dest_buf); +} + +// Make sure we get returns in the expected locations. +TEST(fxcodec, A85TestLineBreaks) { + // Make sure really big values don't break. + uint8_t src_buf[131] = {0}; + // 1 full line + most of a line of normal symbols. + for (int k = 0; k < 116; k += 4) { + src_buf[k] = 1; + src_buf[k + 1] = 2; + src_buf[k + 2] = 3; + src_buf[k + 3] = 4; + } + // Fill in the end, leaving an all zero gap + 3 extra zeros at the end. + for (int k = 120; k < 128; k++) { + src_buf[k] = 1; + src_buf[k + 1] = 2; + src_buf[k + 2] = 3; + src_buf[k + 3] = 4; + } + uint8_t* dest_buf = nullptr; + uint32_t src_size = 131; + uint32_t dest_size = 0; + + CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); + EXPECT_TRUE(pEncoders); + + // Should succeed. + EXPECT_TRUE(pEncoders->A85Encode(src_buf, src_size, &dest_buf, &dest_size)); + + // Should have 75 chars in the first row plus 2 char return, + // 76 chars in the second row plus 2 char return, + // and 9 chars in the last row with 2 terminators. + EXPECT_EQ(166u, dest_size); + + // Check for the returns. + EXPECT_EQ(dest_buf[75], 13); + EXPECT_EQ(dest_buf[76], 10); + EXPECT_EQ(dest_buf[153], 13); + EXPECT_EQ(dest_buf[154], 10); + + FX_Free(dest_buf); +} diff --git a/core/fxcodec/codec/fx_codec_rle_unittest.cpp b/core/fxcodec/codec/fx_codec_rle_unittest.cpp new file mode 100644 index 0000000000..94d87cde92 --- /dev/null +++ b/core/fxcodec/codec/fx_codec_rle_unittest.cpp @@ -0,0 +1,195 @@ +// Copyright 2016 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <stdint.h> + +#include <limits> + +#include "core/fpdfapi/parser/fpdf_parser_decode.h" +#include "core/fxcodec/codec/ccodec_basicmodule.h" +#include "core/fxcodec/fx_codec.h" +#include "testing/fx_string_testhelpers.h" +#include "testing/gtest/include/gtest/gtest.h" + +TEST(fxcodec, RLETestBadInputs) { + uint8_t src_buf[1] = {1}; + uint8_t* dest_buf = nullptr; + uint32_t src_size = 4; + uint32_t dest_size = 0; + + CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); + EXPECT_TRUE(pEncoders); + + // Error codes, not segvs, should callers pass us a nullptr pointer. + EXPECT_FALSE( + pEncoders->RunLengthEncode(src_buf, src_size, &dest_buf, nullptr)); + EXPECT_FALSE( + pEncoders->RunLengthEncode(src_buf, src_size, nullptr, &dest_size)); + EXPECT_FALSE(pEncoders->RunLengthEncode(src_buf, 0, &dest_buf, &dest_size)); + EXPECT_FALSE( + pEncoders->RunLengthEncode(nullptr, src_size, &dest_buf, &dest_size)); +} + +// Check length 1 input works. Check terminating character is applied. +TEST(fxcodec, RLETestShortInput) { + uint8_t src_buf[1] = {1}; + uint8_t* dest_buf = nullptr; + uint32_t src_size = 1; + uint32_t dest_size = 0; + + CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); + EXPECT_TRUE(pEncoders); + + EXPECT_TRUE( + pEncoders->RunLengthEncode(src_buf, src_size, &dest_buf, &dest_size)); + EXPECT_EQ(3u, dest_size); + EXPECT_EQ(dest_buf[0], 0); + EXPECT_EQ(dest_buf[1], 1); + EXPECT_EQ(dest_buf[2], 128); + + FX_Free(dest_buf); +} + +// Check a few basic cases (2 matching runs in a row, matching run followed +// by a nonmatching run, and nonmatching run followed by a matching run). +TEST(fxcodec, RLETestNormalInputs) { + // Match, match + uint8_t src_buf_1[10] = {2, 2, 2, 2, 4, 4, 4, 4, 4, 4}; + + // Match, nonmatch + uint8_t src_buf_2[10] = {2, 2, 2, 2, 1, 2, 3, 4, 5, 6}; + + // Nonmatch, match + uint8_t src_buf_3[10] = {1, 2, 3, 4, 5, 3, 3, 3, 3, 3}; + + uint32_t src_size = 10; + uint32_t dest_size = 0; + uint8_t* dest_buf = nullptr; + + CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); + EXPECT_TRUE(pEncoders); + + // Case 1: + EXPECT_TRUE( + pEncoders->RunLengthEncode(src_buf_1, src_size, &dest_buf, &dest_size)); + uint8_t* decoded_buf = nullptr; + uint32_t decoded_size = 0; + RunLengthDecode(dest_buf, dest_size, decoded_buf, decoded_size); + EXPECT_EQ(decoded_size, src_size); + for (uint32_t i = 0; i < src_size; i++) + EXPECT_EQ(decoded_buf[i], src_buf_1[i]) << " at " << i; + FX_Free(dest_buf); + FX_Free(decoded_buf); + + // Case 2: + dest_buf = nullptr; + dest_size = 0; + EXPECT_TRUE( + pEncoders->RunLengthEncode(src_buf_2, src_size, &dest_buf, &dest_size)); + decoded_buf = nullptr; + decoded_size = 0; + RunLengthDecode(dest_buf, dest_size, decoded_buf, decoded_size); + EXPECT_EQ(decoded_size, src_size); + for (uint32_t i = 0; i < src_size; i++) + EXPECT_EQ(decoded_buf[i], src_buf_2[i]) << " at " << i; + FX_Free(dest_buf); + FX_Free(decoded_buf); + + // Case 3: + dest_buf = nullptr; + dest_size = 0; + EXPECT_TRUE( + pEncoders->RunLengthEncode(src_buf_3, src_size, &dest_buf, &dest_size)); + decoded_buf = nullptr; + decoded_size = 0; + RunLengthDecode(dest_buf, dest_size, decoded_buf, decoded_size); + EXPECT_EQ(decoded_size, src_size); + for (uint32_t i = 0; i < src_size; i++) + EXPECT_EQ(decoded_buf[i], src_buf_3[i]) << " at " << i; + FX_Free(dest_buf); + FX_Free(decoded_buf); +} + +// Check that runs longer than 128 are broken up properly, both matched and +// nonmatched. +TEST(fxcodec, RLETestFullLengthInputs) { + // Match, match + uint8_t src_buf_1[260] = {1}; + + // Match, nonmatch + uint8_t src_buf_2[260] = {2}; + for (uint16_t i = 128; i < 260; i++) + src_buf_2[i] = (uint8_t)(i - 125); + + // Nonmatch, match + uint8_t src_buf_3[260] = {3}; + for (uint8_t i = 0; i < 128; i++) + src_buf_3[i] = i; + + // Nonmatch, nonmatch + uint8_t src_buf_4[260]; + for (uint16_t i = 0; i < 260; i++) + src_buf_4[i] = (uint8_t)(i); + + uint32_t src_size = 260; + uint32_t dest_size = 0; + uint8_t* dest_buf = nullptr; + + CCodec_BasicModule* pEncoders = CCodec_ModuleMgr().GetBasicModule(); + EXPECT_TRUE(pEncoders); + + // Case 1: + EXPECT_TRUE( + pEncoders->RunLengthEncode(src_buf_1, src_size, &dest_buf, &dest_size)); + uint8_t* decoded_buf = nullptr; + uint32_t decoded_size = 0; + RunLengthDecode(dest_buf, dest_size, decoded_buf, decoded_size); + EXPECT_EQ(decoded_size, src_size); + for (uint32_t i = 0; i < src_size; i++) + EXPECT_EQ(decoded_buf[i], src_buf_1[i]) << " at " << i; + FX_Free(dest_buf); + FX_Free(decoded_buf); + + // Case 2: + dest_buf = nullptr; + dest_size = 0; + EXPECT_TRUE( + pEncoders->RunLengthEncode(src_buf_2, src_size, &dest_buf, &dest_size)); + decoded_buf = nullptr; + decoded_size = 0; + RunLengthDecode(dest_buf, dest_size, decoded_buf, decoded_size); + EXPECT_EQ(decoded_size, src_size); + for (uint32_t i = 0; i < src_size; i++) + EXPECT_EQ(decoded_buf[i], src_buf_2[i]) << " at " << i; + FX_Free(dest_buf); + FX_Free(decoded_buf); + + // Case 3: + dest_buf = nullptr; + dest_size = 0; + EXPECT_TRUE( + pEncoders->RunLengthEncode(src_buf_3, src_size, &dest_buf, &dest_size)); + decoded_buf = nullptr; + decoded_size = 0; + RunLengthDecode(dest_buf, dest_size, decoded_buf, decoded_size); + EXPECT_EQ(decoded_size, src_size); + for (uint32_t i = 0; i < src_size; i++) + EXPECT_EQ(decoded_buf[i], src_buf_3[i]) << " at " << i; + FX_Free(dest_buf); + FX_Free(decoded_buf); + + // Case 4: + dest_buf = nullptr; + dest_size = 0; + EXPECT_TRUE( + pEncoders->RunLengthEncode(src_buf_4, src_size, &dest_buf, &dest_size)); + decoded_buf = nullptr; + decoded_size = 0; + RunLengthDecode(dest_buf, dest_size, decoded_buf, decoded_size); + EXPECT_EQ(decoded_size, src_size); + for (uint32_t i = 0; i < src_size; i++) + EXPECT_EQ(decoded_buf[i], src_buf_4[i]) << " at " << i; + FX_Free(dest_buf); + FX_Free(decoded_buf); +} diff --git a/core/fxge/cfx_windowsdevice.h b/core/fxge/cfx_windowsdevice.h index 5a4b901621..6240d84219 100644 --- a/core/fxge/cfx_windowsdevice.h +++ b/core/fxge/cfx_windowsdevice.h @@ -25,6 +25,7 @@ extern bool g_pdfium_print_text_with_gdi; extern PDFiumEnsureTypefaceCharactersAccessible g_pdfium_typeface_accessible_func; #endif +extern int g_pdfium_print_postscript_level; class CFX_WindowsDevice : public CFX_RenderDevice { public: diff --git a/core/fxge/win32/cfx_psrenderer.cpp b/core/fxge/win32/cfx_psrenderer.cpp index c0d7557541..b62d0cb8f5 100644 --- a/core/fxge/win32/cfx_psrenderer.cpp +++ b/core/fxge/win32/cfx_psrenderer.cpp @@ -39,7 +39,7 @@ CFX_PSRenderer::CFX_PSRenderer() { CFX_PSRenderer::~CFX_PSRenderer() {} -#define OUTPUT_PS(str) m_pOutput->OutputPS(str, sizeof str - 1) +#define OUTPUT_PS(str) m_pOutput->OutputPS(str, sizeof(str) - 1) void CFX_PSRenderer::Init(CPSOutput* pOutput, int pslevel, @@ -125,11 +125,9 @@ void CFX_PSRenderer::OutputPath(const CFX_PathData* pPathData, buf << " m "; break; case FXPT_LINETO: - if (flag & FXPT_CLOSEFIGURE) { - buf << " l h "; - } else { - buf << " l "; - } + buf << " l "; + if (flag & FXPT_CLOSEFIGURE) + buf << "h "; break; case FXPT_BEZIERTO: { FX_FLOAT x1 = pPathData->GetPointX(i + 1); @@ -140,12 +138,10 @@ void CFX_PSRenderer::OutputPath(const CFX_PathData* pPathData, pObject2Device->Transform(x1, y1); pObject2Device->Transform(x2, y2); } - buf << " " << x1 << " " << y1 << " " << x2 << " " << y2; - if (flag & FXPT_CLOSEFIGURE) { - buf << " c h\n"; - } else { - buf << " c\n"; - } + buf << " " << x1 << " " << y1 << " " << x2 << " " << y2 << " c"; + if (flag & FXPT_CLOSEFIGURE) + buf << " h"; + buf << "\n"; i += 2; break; } @@ -160,10 +156,12 @@ void CFX_PSRenderer::SetClip_PathFill(const CFX_PathData* pPathData, StartRendering(); OutputPath(pPathData, pObject2Device); CFX_FloatRect rect = pPathData->GetBoundingBox(); - if (pObject2Device) { + if (pObject2Device) rect.Transform(pObject2Device); - } - m_ClipBox.Intersect(rect.GetOuterRect()); + m_ClipBox.left = static_cast<int>(rect.left); + 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 { @@ -263,7 +261,7 @@ void CFX_PSRenderer::SetGraphState(const CFX_GraphStateData* pGraphState) { FXSYS_memcmp(m_CurGraphState.m_DashArray, pGraphState->m_DashArray, sizeof(FX_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"; @@ -281,7 +279,7 @@ void CFX_PSRenderer::SetGraphState(const CFX_GraphStateData* pGraphState) { buf << pGraphState->m_MiterLimit << " M\n"; } m_CurGraphState.Copy(*pGraphState); - m_bGraphStateSet = TRUE; + m_bGraphStateSet = true; if (buf.GetSize()) { m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); } @@ -297,7 +295,7 @@ static void FaxCompressData(uint8_t* src_buf, dest_buf, dest_size); FX_Free(src_buf); } else { - (*dest_buf).reset(src_buf); + dest_buf->reset(src_buf); *dest_size = (width + 7) / 8 * height; } } @@ -315,7 +313,7 @@ static void PSCompressData(int PSLevel, return; } CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); - uint8_t* dest_buf = NULL; + uint8_t* dest_buf = nullptr; uint32_t dest_size = src_size; if (PSLevel >= 3) { if (pEncoders && @@ -334,7 +332,7 @@ static void PSCompressData(int PSLevel, *output_buf = dest_buf; *output_size = dest_size; } else { - *filter = NULL; + *filter = nullptr; FX_Free(dest_buf); } } @@ -407,9 +405,10 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_DIBSource* pSource, } buf << width << " 0 0 -" << height << " 0 " << height << "]currentfile/ASCII85Decode filter "; - if (output_buf.get() != src_buf) + if (output_buf.get() != src_buf) { buf << "<</K -1/EndOfBlock false/Columns " << width << "/Rows " << height << ">>/CCITTFaxDecode filter "; + } if (pSource->IsAlphaMask()) { buf << "iM\n"; } else { @@ -419,23 +418,26 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_DIBSource* pSource, WritePSBinary(output_buf.get(), output_size); output_buf.release(); } else { - CFX_MaybeOwned<CFX_DIBSource> pConverted((CFX_DIBSource*)pSource); + CFX_DIBExtractor source_extractor(pSource); + CFX_MaybeOwned<CFX_DIBSource> pConverted(source_extractor.GetBitmap()); + if (!pConverted.Get()) + return false; switch (pSource->GetFormat()) { case FXDIB_1bppRgb: case FXDIB_Rgb32: - pConverted = pSource->CloneConvert(FXDIB_Rgb); + pConverted = pConverted->CloneConvert(FXDIB_Rgb).release(); break; case FXDIB_8bppRgb: if (pSource->GetPalette()) { - pConverted = pSource->CloneConvert(FXDIB_Rgb); + pConverted = pConverted->CloneConvert(FXDIB_Rgb).release(); } break; case FXDIB_1bppCmyk: - pConverted = pSource->CloneConvert(FXDIB_Cmyk); + pConverted = pConverted->CloneConvert(FXDIB_Cmyk).release(); break; case FXDIB_8bppCmyk: if (pSource->GetPalette()) { - pConverted = pSource->CloneConvert(FXDIB_Cmyk); + pConverted = pConverted->CloneConvert(FXDIB_Cmyk).release(); } break; default: @@ -445,26 +447,23 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_DIBSource* pSource, OUTPUT_PS("\nQ\n"); return false; } - int Bpp = pConverted->GetBPP() / 8; + int bpp = pConverted->GetBPP() / 8; uint8_t* output_buf = nullptr; FX_STRSIZE output_size = 0; const FX_CHAR* filter = nullptr; - if (flags & FXRENDER_IMAGE_LOSSY) { - CCodec_ModuleMgr* pEncoders = CFX_GEModule::Get()->GetCodecModule(); - if (pEncoders && - pEncoders->GetJpegModule()->JpegEncode(pConverted.Get(), &output_buf, - &output_size)) { - filter = "/DCTDecode filter "; - } + if ((m_PSLevel == 2 || flags & FXRENDER_IMAGE_LOSSY) && + CCodec_JpegModule::JpegEncode(pConverted.Get(), &output_buf, + &output_size)) { + filter = "/DCTDecode filter "; } if (!filter) { - int src_pitch = width * Bpp; + int src_pitch = width * bpp; output_size = height * src_pitch; output_buf = FX_Alloc(uint8_t, output_size); for (int row = 0; row < height; row++) { const uint8_t* src_scan = pConverted->GetScanline(row); uint8_t* dest_scan = output_buf + row * src_pitch; - if (Bpp == 3) { + if (bpp == 3) { for (int col = 0; col < width; col++) { *dest_scan++ = src_scan[2]; *dest_scan++ = src_scan[1]; @@ -485,18 +484,13 @@ bool CFX_PSRenderer::DrawDIBits(const CFX_DIBSource* pSource, output_buf = compressed_buf; output_size = compressed_size; } - CFX_DIBSource* converted = pConverted.Get(); - if (converted != pSource) { - delete converted; - pConverted.Reset(); - } buf << " 8["; buf << width << " 0 0 -" << height << " 0 " << height << "]"; buf << "currentfile/ASCII85Decode filter "; if (filter) { buf << filter; } - buf << "false " << Bpp; + buf << "false " << bpp; buf << " colorimage\n"; m_pOutput->OutputPS((const FX_CHAR*)buf.GetBuffer(), buf.GetSize()); WritePSBinary(output_buf, output_size); diff --git a/core/fxge/win32/fx_win32_device.cpp b/core/fxge/win32/fx_win32_device.cpp index 1bfb4b7d6d..c673a18d2d 100644 --- a/core/fxge/win32/fx_win32_device.cpp +++ b/core/fxge/win32/fx_win32_device.cpp @@ -14,10 +14,6 @@ #include "core/fxcrt/cfx_maybe_owned.h" #include "core/fxcrt/fx_memory.h" #include "core/fxcrt/fx_system.h" -#include "core/fxge/cfx_fontmapper.h" -#include "core/fxge/cfx_gemodule.h" -#include "core/fxge/cfx_graphstatedata.h" -#include "core/fxge/cfx_pathdata.h" #include "core/fxge/cfx_windowsdevice.h" #include "core/fxge/dib/dib_int.h" #include "core/fxge/fx_font.h" @@ -697,6 +693,8 @@ bool CFX_Win32FontInfo::GetFontCharset(void* hFont, int& charset) { } // namespace +int g_pdfium_print_postscript_level = 0; + std::unique_ptr<IFX_SystemFontInfo> IFX_SystemFontInfo::CreateDefault( const char** pUnused) { if (IsGDIEnabled()) @@ -1387,7 +1385,13 @@ IFX_RenderDeviceDriver* CFX_WindowsDevice::CreateDriver(HDC hDC) { int obj_type = ::GetObjectType(hDC); bool use_printer = device_type == DT_RASPRINTER || device_type == DT_PLOTTER || obj_type == OBJ_ENHMETADC; - if (use_printer) - return new CGdiPrinterDriver(hDC); - return new CGdiDisplayDriver(hDC); + + 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); } diff --git a/core/fxge/win32/fx_win32_print.cpp b/core/fxge/win32/fx_win32_print.cpp index a8cfb3d1b9..94c415b721 100644 --- a/core/fxge/win32/fx_win32_print.cpp +++ b/core/fxge/win32/fx_win32_print.cpp @@ -11,11 +11,11 @@ #include <vector> #include "core/fxcrt/fx_system.h" -#include "core/fxge/cfx_renderdevice.h" #include "core/fxge/cfx_windowsdevice.h" #include "core/fxge/dib/dib_int.h" #include "core/fxge/fx_freetype.h" #include "core/fxge/ge/fx_text_int.h" +#include "core/fxge/win32/cpsoutput.h" #include "core/fxge/win32/win32_int.h" #include "third_party/base/ptr_util.h" @@ -328,8 +328,8 @@ bool CGdiPrinterDriver::DrawDeviceText(int nChars, #endif } -CPSPrinterDriver::CPSPrinterDriver(HDC hDC, int pslevel, bool bCmykOutput) { - m_hDC = hDC; +CPSPrinterDriver::CPSPrinterDriver(HDC hDC, int pslevel, bool bCmykOutput) + : m_hDC(hDC), m_bCmykOutput(bCmykOutput) { m_HorzSize = ::GetDeviceCaps(m_hDC, HORZSIZE); m_VertSize = ::GetDeviceCaps(m_hDC, VERTSIZE); m_Width = ::GetDeviceCaps(m_hDC, HORZRES); @@ -337,7 +337,6 @@ CPSPrinterDriver::CPSPrinterDriver(HDC hDC, int pslevel, bool bCmykOutput) { 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_bCmykOutput = bCmykOutput; HRGN hRgn = ::CreateRectRgn(0, 0, 1, 1); int ret = ::GetClipRgn(hDC, hRgn); if (ret == 1) { @@ -354,7 +353,7 @@ CPSPrinterDriver::CPSPrinterDriver(HDC hDC, int pslevel, bool bCmykOutput) { path.AppendRect((FX_FLOAT)pRect->left, (FX_FLOAT)pRect->bottom, (FX_FLOAT)pRect->right, (FX_FLOAT)pRect->top); } - m_PSRenderer.SetClip_PathFill(&path, NULL, FXFILL_WINDING); + m_PSRenderer.SetClip_PathFill(&path, nullptr, FXFILL_WINDING); } FX_Free(pData); } |