1// Copyright 2016 PDFium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5// Original code copyright 2014 Foxit Software Inc. http://www.foxitsoftware.com 6 7#include "core/fpdfapi/page/cpdf_allstates.h" 8 9#include <algorithm> 10 11#include "core/fpdfapi/page/cpdf_pageobjectholder.h" 12#include "core/fpdfapi/page/cpdf_streamcontentparser.h" 13#include "core/fpdfapi/page/pageint.h" 14#include "core/fpdfapi/parser/cpdf_array.h" 15#include "core/fpdfapi/parser/cpdf_dictionary.h" 16#include "core/fxge/cfx_graphstatedata.h" 17 18namespace { 19 20FX_FLOAT ClipFloat(FX_FLOAT f) { 21 return std::max(0.0f, std::min(1.0f, f)); 22} 23 24} // namespace 25 26CPDF_AllStates::CPDF_AllStates() 27 : m_TextLeading(0), m_TextRise(0), m_TextHorzScale(1.0f) {} 28 29CPDF_AllStates::~CPDF_AllStates() {} 30 31void CPDF_AllStates::Copy(const CPDF_AllStates& src) { 32 CopyStates(src); 33 m_TextMatrix = src.m_TextMatrix; 34 m_ParentMatrix = src.m_ParentMatrix; 35 m_CTM = src.m_CTM; 36 m_TextPos = src.m_TextPos; 37 m_TextLinePos = src.m_TextLinePos; 38 m_TextLeading = src.m_TextLeading; 39 m_TextRise = src.m_TextRise; 40 m_TextHorzScale = src.m_TextHorzScale; 41} 42 43void CPDF_AllStates::SetLineDash(CPDF_Array* pArray, 44 FX_FLOAT phase, 45 FX_FLOAT scale) { 46 m_GraphState.SetLineDash(pArray, phase, scale); 47} 48 49void CPDF_AllStates::ProcessExtGS(CPDF_Dictionary* pGS, 50 CPDF_StreamContentParser* pParser) { 51 for (const auto& it : *pGS) { 52 const CFX_ByteString& key_str = it.first; 53 CPDF_Object* pElement = it.second.get(); 54 CPDF_Object* pObject = pElement ? pElement->GetDirect() : nullptr; 55 if (!pObject) 56 continue; 57 58 uint32_t key = key_str.GetID(); 59 switch (key) { 60 case FXBSTR_ID('L', 'W', 0, 0): 61 m_GraphState.SetLineWidth(pObject->GetNumber()); 62 break; 63 case FXBSTR_ID('L', 'C', 0, 0): 64 m_GraphState.SetLineCap( 65 static_cast<CFX_GraphStateData::LineCap>(pObject->GetInteger())); 66 break; 67 case FXBSTR_ID('L', 'J', 0, 0): 68 m_GraphState.SetLineJoin( 69 static_cast<CFX_GraphStateData::LineJoin>(pObject->GetInteger())); 70 break; 71 case FXBSTR_ID('M', 'L', 0, 0): 72 m_GraphState.SetMiterLimit(pObject->GetNumber()); 73 break; 74 case FXBSTR_ID('D', 0, 0, 0): { 75 CPDF_Array* pDash = pObject->AsArray(); 76 if (!pDash) 77 break; 78 79 CPDF_Array* pArray = pDash->GetArrayAt(0); 80 if (!pArray) 81 break; 82 83 SetLineDash(pArray, pDash->GetNumberAt(1), 1.0f); 84 break; 85 } 86 case FXBSTR_ID('R', 'I', 0, 0): 87 m_GeneralState.SetRenderIntent(pObject->GetString()); 88 break; 89 case FXBSTR_ID('F', 'o', 'n', 't'): { 90 CPDF_Array* pFont = pObject->AsArray(); 91 if (!pFont) 92 break; 93 94 m_TextState.SetFontSize(pFont->GetNumberAt(1)); 95 m_TextState.SetFont(pParser->FindFont(pFont->GetStringAt(0))); 96 break; 97 } 98 case FXBSTR_ID('T', 'R', 0, 0): 99 if (pGS->KeyExist("TR2")) { 100 continue; 101 } 102 case FXBSTR_ID('T', 'R', '2', 0): 103 m_GeneralState.SetTR(pObject && !pObject->IsName() ? pObject : nullptr); 104 break; 105 case FXBSTR_ID('B', 'M', 0, 0): { 106 CPDF_Array* pArray = pObject->AsArray(); 107 m_GeneralState.SetBlendMode(pArray ? pArray->GetStringAt(0) 108 : pObject->GetString()); 109 if (m_GeneralState.GetBlendType() > FXDIB_BLEND_MULTIPLY) 110 pParser->GetPageObjectHolder()->SetBackgroundAlphaNeeded(true); 111 break; 112 } 113 case FXBSTR_ID('S', 'M', 'a', 's'): 114 if (ToDictionary(pObject)) { 115 m_GeneralState.SetSoftMask(pObject); 116 m_GeneralState.SetSMaskMatrix(pParser->GetCurStates()->m_CTM); 117 } else { 118 m_GeneralState.SetSoftMask(nullptr); 119 } 120 break; 121 case FXBSTR_ID('C', 'A', 0, 0): 122 m_GeneralState.SetStrokeAlpha(ClipFloat(pObject->GetNumber())); 123 break; 124 case FXBSTR_ID('c', 'a', 0, 0): 125 m_GeneralState.SetFillAlpha(ClipFloat(pObject->GetNumber())); 126 break; 127 case FXBSTR_ID('O', 'P', 0, 0): 128 m_GeneralState.SetStrokeOP(!!pObject->GetInteger()); 129 if (!pGS->KeyExist("op")) 130 m_GeneralState.SetFillOP(!!pObject->GetInteger()); 131 break; 132 case FXBSTR_ID('o', 'p', 0, 0): 133 m_GeneralState.SetFillOP(!!pObject->GetInteger()); 134 break; 135 case FXBSTR_ID('O', 'P', 'M', 0): 136 m_GeneralState.SetOPMode(pObject->GetInteger()); 137 break; 138 case FXBSTR_ID('B', 'G', 0, 0): 139 if (pGS->KeyExist("BG2")) { 140 continue; 141 } 142 case FXBSTR_ID('B', 'G', '2', 0): 143 m_GeneralState.SetBG(pObject); 144 break; 145 case FXBSTR_ID('U', 'C', 'R', 0): 146 if (pGS->KeyExist("UCR2")) { 147 continue; 148 } 149 case FXBSTR_ID('U', 'C', 'R', '2'): 150 m_GeneralState.SetUCR(pObject); 151 break; 152 case FXBSTR_ID('H', 'T', 0, 0): 153 m_GeneralState.SetHT(pObject); 154 break; 155 case FXBSTR_ID('F', 'L', 0, 0): 156 m_GeneralState.SetFlatness(pObject->GetNumber()); 157 break; 158 case FXBSTR_ID('S', 'M', 0, 0): 159 m_GeneralState.SetSmoothness(pObject->GetNumber()); 160 break; 161 case FXBSTR_ID('S', 'A', 0, 0): 162 m_GeneralState.SetStrokeAdjust(!!pObject->GetInteger()); 163 break; 164 case FXBSTR_ID('A', 'I', 'S', 0): 165 m_GeneralState.SetAlphaSource(!!pObject->GetInteger()); 166 break; 167 case FXBSTR_ID('T', 'K', 0, 0): 168 m_GeneralState.SetTextKnockout(!!pObject->GetInteger()); 169 break; 170 } 171 } 172 m_GeneralState.SetMatrix(m_CTM); 173} 174