// 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 #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 FindTagParamFromStart(&syntax, "Tf", 2); } ByteString CPDF_DefaultAppearance::GetFont(float* fFontSize) { *fFontSize = 0.0f; if (m_csDA.IsEmpty()) return ByteString(); ByteString csFontNameTag; CPDF_SimpleParser syntax(m_csDA.AsStringView()); if (FindTagParamFromStart(&syntax, "Tf", 2)) { csFontNameTag = ByteString(syntax.GetWord()); csFontNameTag.Delete(0, 1); *fFontSize = FX_atof(syntax.GetWord()); } return PDF_NameDecode(csFontNameTag.AsStringView()); } bool CPDF_DefaultAppearance::HasColor() { if (m_csDA.IsEmpty()) return false; CPDF_SimpleParser syntax(m_csDA.AsStringView()); if (FindTagParamFromStart(&syntax, "g", 1)) return true; if (FindTagParamFromStart(&syntax, "rg", 3)) return true; return FindTagParamFromStart(&syntax, "k", 4); } CFX_Color::Type CPDF_DefaultAppearance::GetColor(float fc[4]) { for (int c = 0; c < 4; c++) fc[c] = 0; if (m_csDA.IsEmpty()) return CFX_Color::kTransparent; CPDF_SimpleParser syntax(m_csDA.AsStringView()); if (FindTagParamFromStart(&syntax, "g", 1)) { fc[0] = FX_atof(syntax.GetWord()); return CFX_Color::kGray; } if (FindTagParamFromStart(&syntax, "rg", 3)) { fc[0] = FX_atof(syntax.GetWord()); fc[1] = FX_atof(syntax.GetWord()); fc[2] = FX_atof(syntax.GetWord()); return CFX_Color::kRGB; } if (FindTagParamFromStart(&syntax, "k", 4)) { fc[0] = FX_atof(syntax.GetWord()); fc[1] = FX_atof(syntax.GetWord()); fc[2] = FX_atof(syntax.GetWord()); fc[3] = FX_atof(syntax.GetWord()); return CFX_Color::kCMYK; } return CFX_Color::kTransparent; } std::pair CPDF_DefaultAppearance::GetColor() { float values[4]; CFX_Color::Type type = GetColor(values); if (type == CFX_Color::kTransparent) return {type, 0}; if (type == CFX_Color::kGray) { int g = static_cast(values[0] * 255 + 0.5f); return {type, ArgbEncode(255, g, g, g)}; } if (type == CFX_Color::kRGB) { int r = static_cast(values[0] * 255 + 0.5f); int g = static_cast(values[1] * 255 + 0.5f); int b = static_cast(values[2] * 255 + 0.5f); return {type, ArgbEncode(255, r, g, b)}; } if (type == CFX_Color::kCMYK) { float r = 1.0f - std::min(1.0f, values[0] + values[3]); float g = 1.0f - std::min(1.0f, values[1] + values[3]); float b = 1.0f - std::min(1.0f, values[2] + values[3]); return {type, ArgbEncode(255, static_cast(r * 255 + 0.5f), static_cast(g * 255 + 0.5f), static_cast(b * 255 + 0.5f))}; } NOTREACHED(); return {CFX_Color::kTransparent, 0}; } bool CPDF_DefaultAppearance::FindTagParamFromStartForTesting( CPDF_SimpleParser* parser, const ByteStringView& token, int nParams) { return FindTagParamFromStart(parser, token, nParams); }