Home | History | Annotate | Download | only in page
      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 
     18 namespace {
     19 
     20 FX_FLOAT ClipFloat(FX_FLOAT f) {
     21   return std::max(0.0f, std::min(1.0f, f));
     22 }
     23 
     24 }  // namespace
     25 
     26 CPDF_AllStates::CPDF_AllStates()
     27     : m_TextLeading(0), m_TextRise(0), m_TextHorzScale(1.0f) {}
     28 
     29 CPDF_AllStates::~CPDF_AllStates() {}
     30 
     31 void 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 
     43 void CPDF_AllStates::SetLineDash(CPDF_Array* pArray,
     44                                  FX_FLOAT phase,
     45                                  FX_FLOAT scale) {
     46   m_GraphState.SetLineDash(pArray, phase, scale);
     47 }
     48 
     49 void 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