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 --- 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 +++--- 5 files changed, 124 insertions(+), 19 deletions(-) create mode 100644 core/fpdfdoc/cpdf_defaultappearance_unittest.cpp (limited to 'core/fpdfdoc') 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) -- cgit v1.2.3