// Copyright 2014 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. // Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com #include "core/fpdfapi/page/pageint.h" #include #include #include #include "core/fpdfapi/edit/cpdf_creator.h" #include "core/fpdfapi/font/cpdf_font.h" #include "core/fpdfapi/font/cpdf_type3font.h" #include "core/fpdfapi/page/cpdf_allstates.h" #include "core/fpdfapi/page/cpdf_docpagedata.h" #include "core/fpdfapi/page/cpdf_form.h" #include "core/fpdfapi/page/cpdf_formobject.h" #include "core/fpdfapi/page/cpdf_image.h" #include "core/fpdfapi/page/cpdf_imageobject.h" #include "core/fpdfapi/page/cpdf_meshstream.h" #include "core/fpdfapi/page/cpdf_pageobject.h" #include "core/fpdfapi/page/cpdf_pathobject.h" #include "core/fpdfapi/page/cpdf_shadingobject.h" #include "core/fpdfapi/page/cpdf_shadingpattern.h" #include "core/fpdfapi/page/cpdf_textobject.h" #include "core/fpdfapi/parser/cpdf_array.h" #include "core/fpdfapi/parser/cpdf_dictionary.h" #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_reference.h" #include "core/fpdfapi/parser/cpdf_stream.h" #include "core/fpdfapi/parser/cpdf_stream_acc.h" #include "core/fpdfapi/parser/fpdf_parser_decode.h" #include "core/fxcrt/fx_safe_types.h" #include "core/fxge/cfx_graphstatedata.h" #include "core/fxge/cfx_pathdata.h" #include "third_party/base/ptr_util.h" namespace { struct PDF_AbbrPair { const FX_CHAR* abbr; const FX_CHAR* full_name; }; const PDF_AbbrPair PDF_InlineKeyAbbr[] = { {"BPC", "BitsPerComponent"}, {"CS", "ColorSpace"}, {"D", "Decode"}, {"DP", "DecodeParms"}, {"F", "Filter"}, {"H", "Height"}, {"IM", "ImageMask"}, {"I", "Interpolate"}, {"W", "Width"}, }; const PDF_AbbrPair PDF_InlineValueAbbr[] = { {"G", "DeviceGray"}, {"RGB", "DeviceRGB"}, {"CMYK", "DeviceCMYK"}, {"I", "Indexed"}, {"AHx", "ASCIIHexDecode"}, {"A85", "ASCII85Decode"}, {"LZW", "LZWDecode"}, {"Fl", "FlateDecode"}, {"RL", "RunLengthDecode"}, {"CCF", "CCITTFaxDecode"}, {"DCT", "DCTDecode"}, }; struct AbbrReplacementOp { bool is_replace_key; CFX_ByteString key; CFX_ByteStringC replacement; }; CFX_ByteStringC PDF_FindFullName(const PDF_AbbrPair* table, size_t count, const CFX_ByteStringC& abbr) { auto it = std::find_if( table, table + count, [abbr](const PDF_AbbrPair& pair) { return pair.abbr == abbr; }); return it != table + count ? CFX_ByteStringC(it->full_name) : CFX_ByteStringC(); } } // namespace CFX_ByteStringC PDF_FindKeyAbbreviationForTesting(const CFX_ByteStringC& abbr) { return PDF_FindFullName(PDF_InlineKeyAbbr, FX_ArraySize(PDF_InlineKeyAbbr), abbr); } CFX_ByteStringC PDF_FindValueAbbreviationForTesting( const CFX_ByteStringC& abbr) { return PDF_FindFullName(PDF_InlineValueAbbr, FX_ArraySize(PDF_InlineValueAbbr), abbr); } void PDF_ReplaceAbbr(CPDF_Object* pObj) { switch (pObj->GetType()) { case CPDF_Object::DICTIONARY: { CPDF_Dictionary* pDict = pObj->AsDictionary(); std::vector replacements; for (const auto& it : *pDict) { CFX_ByteString key = it.first; CPDF_Object* value = it.second; CFX_ByteStringC fullname = PDF_FindFullName(PDF_InlineKeyAbbr, FX_ArraySize(PDF_InlineKeyAbbr), key.AsStringC()); if (!fullname.IsEmpty()) { AbbrReplacementOp op; op.is_replace_key = true; op.key = key; op.replacement = fullname; replacements.push_back(op); key = fullname; } if (value->IsName()) { CFX_ByteString name = value->GetString(); fullname = PDF_FindFullName(PDF_InlineValueAbbr, FX_ArraySize(PDF_InlineValueAbbr), name.AsStringC()); if (!fullname.IsEmpty()) { AbbrReplacementOp op; op.is_replace_key = false; op.key = key; op.replacement = fullname; replacements.push_back(op); } } else { PDF_ReplaceAbbr(value); } } for (const auto& op : replacements) { if (op.is_replace_key) pDict->ReplaceKey(op.key, CFX_ByteString(op.replacement)); else pDict->SetNameFor(op.key, CFX_ByteString(op.replacement)); } break; } case CPDF_Object::ARRAY: { CPDF_Array* pArray = pObj->AsArray(); for (size_t i = 0; i < pArray->GetCount(); i++) { CPDF_Object* pElement = pArray->GetObjectAt(i); if (pElement->IsName()) { CFX_ByteString name = pElement->GetString(); CFX_ByteStringC fullname = PDF_FindFullName( PDF_InlineValueAbbr, FX_ArraySize(PDF_InlineValueAbbr), name.AsStringC()); if (!fullname.IsEmpty()) { pArray->SetAt(i, new CPDF_Name(CFX_ByteString(fullname))); } } else { PDF_ReplaceAbbr(pElement); } } break; } default: break; } }