blob: b6f0bc605cb8e4714f495641bf867adc9d8c58d5 [file] [log] [blame]
// 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 <memory>
#include <utility>
#include <vector>
#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<AbbrReplacementOp> 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;
}
}