From 53a8093c6ef694ec520fe0b087fbac86af97f5e8 Mon Sep 17 00:00:00 2001 From: Dan Sinclair Date: Wed, 28 Mar 2018 20:00:35 +0000 Subject: Use CPDF_DefaultAppearance instead of custom parsing This CL moves code over to using CPDF_DefaultAppearance instead of calling the CPDF_SimpleParser directly. This means the code for finding a specific tag start can move into CPDF_DefaultAppearance directly. Change-Id: I1dc64e54aedd03d059b963121d466f3eb75c17db Reviewed-on: https://pdfium-review.googlesource.com/28410 Reviewed-by: Henrique Nakashima Commit-Queue: dsinclair --- BUILD.gn | 1 + core/fpdfapi/parser/cpdf_simple_parser.cpp | 34 ----------- core/fpdfapi/parser/cpdf_simple_parser.h | 7 +-- .../fpdfapi/parser/cpdf_simple_parser_unittest.cpp | 36 ------------ core/fpdfdoc/cpdf_defaultappearance.cpp | 65 +++++++++++++++++++--- core/fpdfdoc/cpdf_defaultappearance.h | 5 ++ core/fpdfdoc/cpdf_defaultappearance_unittest.cpp | 47 ++++++++++++++++ core/fpdfdoc/cpdf_formfield.cpp | 11 ++-- core/fpdfdoc/cpvt_generateap.cpp | 15 +++-- core/fxge/cfx_color.cpp | 36 ++++++------ fpdfsdk/formfiller/cba_fontmap.cpp | 10 ++-- 11 files changed, 152 insertions(+), 115 deletions(-) create mode 100644 core/fpdfdoc/cpdf_defaultappearance_unittest.cpp diff --git a/BUILD.gn b/BUILD.gn index a62b028f27..c6aee5c645 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -2885,6 +2885,7 @@ test("pdfium_unittests") { "core/fpdfapi/parser/cpdf_simple_parser_unittest.cpp", "core/fpdfapi/parser/cpdf_syntax_parser_unittest.cpp", "core/fpdfapi/parser/fpdf_parser_decode_unittest.cpp", + "core/fpdfdoc/cpdf_defaultappearance_unittest.cpp", "core/fpdfdoc/cpdf_dest_unittest.cpp", "core/fpdfdoc/cpdf_filespec_unittest.cpp", "core/fpdfdoc/cpdf_formfield_unittest.cpp", diff --git a/core/fpdfapi/parser/cpdf_simple_parser.cpp b/core/fpdfapi/parser/cpdf_simple_parser.cpp index 47ce1ad55e..45ea0d4528 100644 --- a/core/fpdfapi/parser/cpdf_simple_parser.cpp +++ b/core/fpdfapi/parser/cpdf_simple_parser.cpp @@ -6,8 +6,6 @@ #include "core/fpdfapi/parser/cpdf_simple_parser.h" -#include - #include "core/fpdfapi/parser/fpdf_parser_utility.h" CPDF_SimpleParser::CPDF_SimpleParser(const ByteStringView& str) : data_(str) {} @@ -129,35 +127,3 @@ ByteStringView CPDF_SimpleParser::GetWord() { } return data_.Mid(start_pos, dwSize); } - -bool CPDF_SimpleParser::FindTagParamFromStart(const ByteStringView& token, - int nParams) { - nParams++; - - std::vector pBuf(nParams); - int buf_index = 0; - int buf_count = 0; - cur_pos_ = 0; - while (1) { - pBuf[buf_index++] = cur_pos_; - if (buf_index == nParams) - buf_index = 0; - - buf_count++; - if (buf_count > nParams) - buf_count = nParams; - - ByteStringView word = GetWord(); - if (word.IsEmpty()) - return false; - - if (word == token) { - if (buf_count < nParams) - continue; - - cur_pos_ = pBuf[buf_index]; - return true; - } - } - return false; -} diff --git a/core/fpdfapi/parser/cpdf_simple_parser.h b/core/fpdfapi/parser/cpdf_simple_parser.h index f02a58c98b..8a07323a69 100644 --- a/core/fpdfapi/parser/cpdf_simple_parser.h +++ b/core/fpdfapi/parser/cpdf_simple_parser.h @@ -19,11 +19,8 @@ class CPDF_SimpleParser { ByteStringView GetWord(); - // Find the token and its |nParams| parameters from the start of data, - // and move the current position to the start of those parameters. - bool FindTagParamFromStart(const ByteStringView& token, int nParams); - - uint32_t GetCurPosForTest() const { return cur_pos_; } + void SetCurPos(uint32_t pos) { cur_pos_ = pos; } + uint32_t GetCurPos() const { return cur_pos_; } private: const ByteStringView data_; diff --git a/core/fpdfapi/parser/cpdf_simple_parser_unittest.cpp b/core/fpdfapi/parser/cpdf_simple_parser_unittest.cpp index b53b6c6c7f..2fb50f1ff3 100644 --- a/core/fpdfapi/parser/cpdf_simple_parser_unittest.cpp +++ b/core/fpdfapi/parser/cpdf_simple_parser_unittest.cpp @@ -59,39 +59,3 @@ TEST(SimpleParserTest, GetWord) { << " for case " << i; } } - -TEST(SimpleParserTest, FindTagParamFromStart) { - static const struct FindTagTestStruct { - const unsigned char* input; - unsigned int input_size; - const char* token; - int num_params; - bool result; - unsigned int result_pos; - } test_data[] = { - // Empty strings. - STR_IN_TEST_CASE("", "Tj", 1, false, 0), - STR_IN_TEST_CASE("", "", 1, false, 0), - // Empty token. - STR_IN_TEST_CASE(" T j", "", 1, false, 5), - // No parameter. - STR_IN_TEST_CASE("Tj", "Tj", 1, false, 2), - STR_IN_TEST_CASE("(Tj", "Tj", 1, false, 3), - // Partial token match. - STR_IN_TEST_CASE("\r12\t34 56 78Tj", "Tj", 1, false, 15), - // Regular cases with various parameters. - STR_IN_TEST_CASE("\r\0abd Tj", "Tj", 1, true, 0), - STR_IN_TEST_CASE("12 4 Tj 3 46 Tj", "Tj", 1, true, 2), - STR_IN_TEST_CASE("er^ 2 (34) (5667) Tj", "Tj", 2, true, 5), - STR_IN_TEST_CASE("<344> (232)\t343.4\n12 45 Tj", "Tj", 3, true, 11), - STR_IN_TEST_CASE("1 2 3 4 5 6 7 8 cm", "cm", 6, true, 3), - }; - for (size_t i = 0; i < FX_ArraySize(test_data); ++i) { - const FindTagTestStruct& data = test_data[i]; - CPDF_SimpleParser parser(ByteStringView(data.input, data.input_size)); - EXPECT_EQ(data.result, - parser.FindTagParamFromStart(data.token, data.num_params)) - << " for case " << i; - EXPECT_EQ(data.result_pos, parser.GetCurPosForTest()) << " for case " << i; - } -} diff --git a/core/fpdfdoc/cpdf_defaultappearance.cpp b/core/fpdfdoc/cpdf_defaultappearance.cpp index cae553a7c2..8878dc0093 100644 --- a/core/fpdfdoc/cpdf_defaultappearance.cpp +++ b/core/fpdfdoc/cpdf_defaultappearance.cpp @@ -7,17 +7,58 @@ #include "core/fpdfdoc/cpdf_defaultappearance.h" #include +#include #include "core/fpdfapi/parser/cpdf_simple_parser.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fxge/cfx_color.h" +namespace { + +// Find the token and its |nParams| parameters from the start of data, +// and move the current position to the start of those parameters. +bool FindTagParamFromStart(CPDF_SimpleParser* parser, + const ByteStringView& token, + int nParams) { + nParams++; + + std::vector pBuf(nParams); + int buf_index = 0; + int buf_count = 0; + + parser->SetCurPos(0); + while (1) { + pBuf[buf_index++] = parser->GetCurPos(); + if (buf_index == nParams) + buf_index = 0; + + buf_count++; + if (buf_count > nParams) + buf_count = nParams; + + ByteStringView word = parser->GetWord(); + if (word.IsEmpty()) + return false; + + if (word == token) { + if (buf_count < nParams) + continue; + + parser->SetCurPos(pBuf[buf_index]); + return true; + } + } + return false; +} + +} // namespace + bool CPDF_DefaultAppearance::HasFont() { if (m_csDA.IsEmpty()) return false; CPDF_SimpleParser syntax(m_csDA.AsStringView()); - return syntax.FindTagParamFromStart("Tf", 2); + return FindTagParamFromStart(&syntax, "Tf", 2); } ByteString CPDF_DefaultAppearance::GetFont(float* fFontSize) { @@ -27,7 +68,7 @@ ByteString CPDF_DefaultAppearance::GetFont(float* fFontSize) { ByteString csFontNameTag; CPDF_SimpleParser syntax(m_csDA.AsStringView()); - if (syntax.FindTagParamFromStart("Tf", 2)) { + if (FindTagParamFromStart(&syntax, "Tf", 2)) { csFontNameTag = ByteString(syntax.GetWord()); csFontNameTag.Delete(0, 1); *fFontSize = FX_atof(syntax.GetWord()); @@ -40,11 +81,11 @@ bool CPDF_DefaultAppearance::HasColor() { return false; CPDF_SimpleParser syntax(m_csDA.AsStringView()); - if (syntax.FindTagParamFromStart("g", 1)) + if (FindTagParamFromStart(&syntax, "g", 1)) return true; - if (syntax.FindTagParamFromStart("rg", 3)) + if (FindTagParamFromStart(&syntax, "rg", 3)) return true; - return syntax.FindTagParamFromStart("k", 4); + return FindTagParamFromStart(&syntax, "k", 4); } void CPDF_DefaultAppearance::GetColor(int& iColorType, float fc[4]) { @@ -56,19 +97,19 @@ void CPDF_DefaultAppearance::GetColor(int& iColorType, float fc[4]) { return; CPDF_SimpleParser syntax(m_csDA.AsStringView()); - if (syntax.FindTagParamFromStart("g", 1)) { + if (FindTagParamFromStart(&syntax, "g", 1)) { iColorType = CFX_Color::kGray; fc[0] = FX_atof(syntax.GetWord()); return; } - if (syntax.FindTagParamFromStart("rg", 3)) { + if (FindTagParamFromStart(&syntax, "rg", 3)) { iColorType = CFX_Color::kRGB; fc[0] = FX_atof(syntax.GetWord()); fc[1] = FX_atof(syntax.GetWord()); fc[2] = FX_atof(syntax.GetWord()); return; } - if (syntax.FindTagParamFromStart("k", 4)) { + if (FindTagParamFromStart(&syntax, "k", 4)) { iColorType = CFX_Color::kCMYK; fc[0] = FX_atof(syntax.GetWord()); fc[1] = FX_atof(syntax.GetWord()); @@ -104,4 +145,12 @@ void CPDF_DefaultAppearance::GetColor(FX_ARGB& color, int& iColorType) { static_cast(g * 255 + 0.5f), static_cast(b * 255 + 0.5f)); } + NOTREACHED(); +} + +bool CPDF_DefaultAppearance::FindTagParamFromStartForTesting( + CPDF_SimpleParser* parser, + const ByteStringView& token, + int nParams) { + return FindTagParamFromStart(parser, token, nParams); } diff --git a/core/fpdfdoc/cpdf_defaultappearance.h b/core/fpdfdoc/cpdf_defaultappearance.h index af13a3f8bc..79ad0bb526 100644 --- a/core/fpdfdoc/cpdf_defaultappearance.h +++ b/core/fpdfdoc/cpdf_defaultappearance.h @@ -7,6 +7,7 @@ #ifndef CORE_FPDFDOC_CPDF_DEFAULTAPPEARANCE_H_ #define CORE_FPDFDOC_CPDF_DEFAULTAPPEARANCE_H_ +#include "core/fpdfapi/parser/cpdf_simple_parser.h" #include "core/fpdfdoc/cpdf_defaultappearance.h" #include "core/fxcrt/fx_coordinates.h" #include "core/fxcrt/fx_string.h" @@ -29,6 +30,10 @@ class CPDF_DefaultAppearance { void GetColor(int& iColorType, float fc[4]); void GetColor(FX_ARGB& color, int& iColorType); + bool FindTagParamFromStartForTesting(CPDF_SimpleParser* parser, + const ByteStringView& token, + int nParams); + private: ByteString m_csDA; }; diff --git a/core/fpdfdoc/cpdf_defaultappearance_unittest.cpp b/core/fpdfdoc/cpdf_defaultappearance_unittest.cpp new file mode 100644 index 0000000000..031fa8c89d --- /dev/null +++ b/core/fpdfdoc/cpdf_defaultappearance_unittest.cpp @@ -0,0 +1,47 @@ +// Copyright 2018 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 "core/fpdfdoc/cpdf_defaultappearance.h" + +#include "testing/gtest/include/gtest/gtest.h" +#include "testing/test_support.h" + +TEST(CPDFDefaultAppearanceTest, FindTagParamFromStart) { + static const struct FindTagTestStruct { + const unsigned char* input; + unsigned int input_size; + const char* token; + int num_params; + bool result; + unsigned int result_pos; + } test_data[] = { + // Empty strings. + STR_IN_TEST_CASE("", "Tj", 1, false, 0), + STR_IN_TEST_CASE("", "", 1, false, 0), + // Empty token. + STR_IN_TEST_CASE(" T j", "", 1, false, 5), + // No parameter. + STR_IN_TEST_CASE("Tj", "Tj", 1, false, 2), + STR_IN_TEST_CASE("(Tj", "Tj", 1, false, 3), + // Partial token match. + STR_IN_TEST_CASE("\r12\t34 56 78Tj", "Tj", 1, false, 15), + // Regular cases with various parameters. + STR_IN_TEST_CASE("\r\0abd Tj", "Tj", 1, true, 0), + STR_IN_TEST_CASE("12 4 Tj 3 46 Tj", "Tj", 1, true, 2), + STR_IN_TEST_CASE("er^ 2 (34) (5667) Tj", "Tj", 2, true, 5), + STR_IN_TEST_CASE("<344> (232)\t343.4\n12 45 Tj", "Tj", 3, true, 11), + STR_IN_TEST_CASE("1 2 3 4 5 6 7 8 cm", "cm", 6, true, 3), + }; + + CPDF_DefaultAppearance da; + for (size_t i = 0; i < FX_ArraySize(test_data); ++i) { + CPDF_SimpleParser parser( + ByteStringView(test_data[i].input, test_data[i].input_size)); + EXPECT_EQ(test_data[i].result, + da.FindTagParamFromStartForTesting(&parser, test_data[i].token, + test_data[i].num_params)) + << " for case " << i; + EXPECT_EQ(test_data[i].result_pos, parser.GetCurPos()) << " for case " << i; + } +} diff --git a/core/fpdfdoc/cpdf_formfield.cpp b/core/fpdfdoc/cpdf_formfield.cpp index 679acd1dc8..f3dcac2228 100644 --- a/core/fpdfdoc/cpdf_formfield.cpp +++ b/core/fpdfdoc/cpdf_formfield.cpp @@ -15,9 +15,9 @@ #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/parser/cpdf_name.h" #include "core/fpdfapi/parser/cpdf_number.h" -#include "core/fpdfapi/parser/cpdf_simple_parser.h" #include "core/fpdfapi/parser/cpdf_string.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" +#include "core/fpdfdoc/cpdf_defaultappearance.h" #include "core/fpdfdoc/cpdf_formcontrol.h" #include "core/fpdfdoc/cpdf_interform.h" #include "core/fpdfdoc/cpvt_generateap.h" @@ -914,15 +914,16 @@ void CPDF_FormField::LoadDA() { if (!pFont) return; - CPDF_SimpleParser syntax(DA.AsStringView()); - syntax.FindTagParamFromStart("Tf", 2); - ByteString font_name(syntax.GetWord()); + CPDF_DefaultAppearance appearance(DA); + if (!appearance.HasFont()) + return; + + ByteString font_name = appearance.GetFont(&m_FontSize); CPDF_Dictionary* pFontDict = pFont->GetDictFor(font_name); if (!pFontDict) return; m_pFont = m_pForm->GetDocument()->LoadFont(pFontDict); - m_FontSize = FX_atof(syntax.GetWord()); } bool CPDF_FormField::NotifyBeforeSelectionChange(const WideString& value) { diff --git a/core/fpdfdoc/cpvt_generateap.cpp b/core/fpdfdoc/cpvt_generateap.cpp index 4138b21a6b..a6a64aaf8d 100644 --- a/core/fpdfdoc/cpvt_generateap.cpp +++ b/core/fpdfdoc/cpvt_generateap.cpp @@ -19,11 +19,11 @@ #include "core/fpdfapi/parser/cpdf_name.h" #include "core/fpdfapi/parser/cpdf_number.h" #include "core/fpdfapi/parser/cpdf_reference.h" -#include "core/fpdfapi/parser/cpdf_simple_parser.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_string.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fpdfdoc/cpdf_annot.h" +#include "core/fpdfdoc/cpdf_defaultappearance.h" #include "core/fpdfdoc/cpdf_formfield.h" #include "core/fpdfdoc/cpvt_fontmap.h" #include "core/fpdfdoc/cpvt_word.h" @@ -922,14 +922,17 @@ void CPVT_GenerateAP::GenerateFormAP(Type type, if (DA.IsEmpty()) return; - CPDF_SimpleParser syntax(DA.AsStringView()); - syntax.FindTagParamFromStart("Tf", 2); - ByteString sFontName(syntax.GetWord()); - sFontName = PDF_NameDecode(sFontName.AsStringView()); + CPDF_DefaultAppearance appearance(DA); + if (!appearance.HasFont()) + return; + + ASSERT(appearance.HasFont()); + float fFontSize = 0; + ByteString sFontName = + PDF_NameDecode(appearance.GetFont(&fFontSize).AsStringView()); if (sFontName.IsEmpty()) return; - float fFontSize = FX_atof(syntax.GetWord()); CFX_Color crText = CFX_Color::ParseColor(DA); CPDF_Dictionary* pDRDict = pFormDict->GetDictFor("DR"); if (!pDRDict) diff --git a/core/fxge/cfx_color.cpp b/core/fxge/cfx_color.cpp index 42ab39d670..5175adc50a 100644 --- a/core/fxge/cfx_color.cpp +++ b/core/fxge/cfx_color.cpp @@ -9,7 +9,7 @@ #include #include "core/fpdfapi/parser/cpdf_array.h" -#include "core/fpdfapi/parser/cpdf_simple_parser.h" +#include "core/fpdfdoc/cpdf_defaultappearance.h" namespace { @@ -84,23 +84,25 @@ CFX_Color CFX_Color::ParseColor(const CPDF_Array& array) { // Static. CFX_Color CFX_Color::ParseColor(const ByteString& str) { - CPDF_SimpleParser syntax(str.AsStringView()); - if (syntax.FindTagParamFromStart("g", 1)) - return CFX_Color(CFX_Color::kGray, FX_atof(syntax.GetWord())); - - if (syntax.FindTagParamFromStart("rg", 3)) { - float f1 = FX_atof(syntax.GetWord()); - float f2 = FX_atof(syntax.GetWord()); - float f3 = FX_atof(syntax.GetWord()); - return CFX_Color(CFX_Color::kRGB, f1, f2, f3); - } - if (syntax.FindTagParamFromStart("k", 4)) { - float f1 = FX_atof(syntax.GetWord()); - float f2 = FX_atof(syntax.GetWord()); - float f3 = FX_atof(syntax.GetWord()); - float f4 = FX_atof(syntax.GetWord()); - return CFX_Color(CFX_Color::kCMYK, f1, f2, f3, f4); + CPDF_DefaultAppearance appearance(str); + ASSERT(appearance.HasColor()); + + int color_type; + float values[4]; + appearance.GetColor(color_type, values); + + if (color_type == CFX_Color::kTransparent) + return CFX_Color(CFX_Color::kTransparent); + if (color_type == CFX_Color::kGray) + return CFX_Color(CFX_Color::kGray, values[0]); + if (color_type == CFX_Color::kRGB) + return CFX_Color(CFX_Color::kRGB, values[0], values[1], values[2]); + if (color_type == CFX_Color::kCMYK) { + return CFX_Color(CFX_Color::kCMYK, values[0], values[1], values[2], + values[3]); } + + NOTREACHED(); return CFX_Color(CFX_Color::kTransparent); } diff --git a/fpdfsdk/formfiller/cba_fontmap.cpp b/fpdfsdk/formfiller/cba_fontmap.cpp index 8e4ac469a5..b7e14b4636 100644 --- a/fpdfsdk/formfiller/cba_fontmap.cpp +++ b/fpdfsdk/formfiller/cba_fontmap.cpp @@ -12,9 +12,9 @@ #include "core/fpdfapi/page/cpdf_page.h" #include "core/fpdfapi/parser/cpdf_document.h" #include "core/fpdfapi/parser/cpdf_reference.h" -#include "core/fpdfapi/parser/cpdf_simple_parser.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" +#include "core/fpdfdoc/cpdf_defaultappearance.h" #include "core/fpdfdoc/cpdf_formfield.h" #include "core/fxge/cfx_substfont.h" #include "fpdfsdk/cpdfsdk_annot.h" @@ -216,10 +216,12 @@ CPDF_Font* CBA_FontMap::GetAnnotDefaultFont(ByteString* sAlias) { if (sDA.IsEmpty()) return nullptr; - CPDF_SimpleParser syntax(sDA.AsStringView()); - syntax.FindTagParamFromStart("Tf", 2); + CPDF_DefaultAppearance appearance(sDA); + ASSERT(appearance.HasFont()); - ByteString sDecodedFontName = PDF_NameDecode(syntax.GetWord()); + float font_size; + ByteString sDecodedFontName = + PDF_NameDecode(appearance.GetFont(&font_size).AsStringView()); *sAlias = sDecodedFontName.Right(sDecodedFontName.GetLength() - 1); CPDF_Dictionary* pFontDict = nullptr; -- cgit v1.2.3