blob: 012c255f28d369afe23089f3ea0c3682599e3334 [file] [log] [blame]
// 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.
// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com
#include "core/fpdfdoc/cpdf_defaultappearance.h"
#include <algorithm>
#include <vector>
#include "core/fpdfapi/parser/cpdf_simple_parser.h"
#include "core/fpdfapi/parser/fpdf_parser_utility.h"
#include "core/fxge/cfx_color.h"
#include "third_party/base/notreached.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,
ByteStringView token,
int nParams) {
nParams++;
std::vector<uint32_t> 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
Optional<ByteString> CPDF_DefaultAppearance::GetFont(float* fFontSize) {
*fFontSize = 0.0f;
if (m_csDA.IsEmpty())
return {};
ByteString csFontNameTag;
CPDF_SimpleParser syntax(m_csDA.AsStringView().raw_span());
if (FindTagParamFromStart(&syntax, "Tf", 2)) {
csFontNameTag = ByteString(syntax.GetWord());
csFontNameTag.Delete(0, 1);
*fFontSize = StringToFloat(syntax.GetWord());
}
return {PDF_NameDecode(csFontNameTag.AsStringView())};
}
Optional<CFX_Color> CPDF_DefaultAppearance::GetColor() const {
if (m_csDA.IsEmpty())
return {};
float fc[4];
CPDF_SimpleParser syntax(m_csDA.AsStringView().raw_span());
if (FindTagParamFromStart(&syntax, "g", 1)) {
fc[0] = StringToFloat(syntax.GetWord());
return CFX_Color(CFX_Color::kGray, fc[0]);
}
if (FindTagParamFromStart(&syntax, "rg", 3)) {
fc[0] = StringToFloat(syntax.GetWord());
fc[1] = StringToFloat(syntax.GetWord());
fc[2] = StringToFloat(syntax.GetWord());
return CFX_Color(CFX_Color::kRGB, fc[0], fc[1], fc[2]);
}
if (FindTagParamFromStart(&syntax, "k", 4)) {
fc[0] = StringToFloat(syntax.GetWord());
fc[1] = StringToFloat(syntax.GetWord());
fc[2] = StringToFloat(syntax.GetWord());
fc[3] = StringToFloat(syntax.GetWord());
return CFX_Color(CFX_Color::kCMYK, fc[0], fc[1], fc[2], fc[3]);
}
return {};
}
std::pair<Optional<CFX_Color::Type>, FX_ARGB>
CPDF_DefaultAppearance::GetColorARGB() const {
Optional<CFX_Color> maybe_color = GetColor();
if (!maybe_color.has_value())
return {{}, 0};
const CFX_Color& color = maybe_color.value();
if (color.nColorType == CFX_Color::kGray) {
int g = static_cast<int>(color.fColor1 * 255 + 0.5f);
return {CFX_Color::kGray, ArgbEncode(255, g, g, g)};
}
if (color.nColorType == CFX_Color::kRGB) {
int r = static_cast<int>(color.fColor1 * 255 + 0.5f);
int g = static_cast<int>(color.fColor2 * 255 + 0.5f);
int b = static_cast<int>(color.fColor3 * 255 + 0.5f);
return {CFX_Color::kRGB, ArgbEncode(255, r, g, b)};
}
if (color.nColorType == CFX_Color::kCMYK) {
float r = 1.0f - std::min(1.0f, color.fColor1 + color.fColor4);
float g = 1.0f - std::min(1.0f, color.fColor2 + color.fColor4);
float b = 1.0f - std::min(1.0f, color.fColor3 + color.fColor4);
return {CFX_Color::kCMYK, ArgbEncode(255, static_cast<int>(r * 255 + 0.5f),
static_cast<int>(g * 255 + 0.5f),
static_cast<int>(b * 255 + 0.5f))};
}
NOTREACHED();
return {{}, 0};
}
bool CPDF_DefaultAppearance::FindTagParamFromStartForTesting(
CPDF_SimpleParser* parser,
ByteStringView token,
int nParams) {
return FindTagParamFromStart(parser, token, nParams);
}