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_color.h"
      8 
      9 #include "core/fpdfapi/page/cpdf_docpagedata.h"
     10 #include "core/fpdfapi/parser/cpdf_array.h"
     11 #include "core/fpdfapi/parser/cpdf_document.h"
     12 #include "core/fxcrt/fx_system.h"
     13 
     14 CPDF_Color::CPDF_Color() {}
     15 
     16 CPDF_Color::~CPDF_Color() {
     17   ReleaseBuffer();
     18   ReleaseColorSpace();
     19 }
     20 
     21 bool CPDF_Color::IsPattern() const {
     22   return m_pCS && IsPatternInternal();
     23 }
     24 
     25 void CPDF_Color::ReleaseBuffer() {
     26   if (!m_pBuffer)
     27     return;
     28 
     29   if (IsPatternInternal()) {
     30     PatternValue* pvalue = reinterpret_cast<PatternValue*>(m_pBuffer);
     31     CPDF_Pattern* pPattern =
     32         pvalue->m_pCountedPattern ? pvalue->m_pCountedPattern->get() : nullptr;
     33     if (pPattern) {
     34       CPDF_DocPageData* pPageData = pPattern->document()->GetPageData();
     35       if (pPageData)
     36         pPageData->ReleasePattern(pPattern->pattern_obj());
     37     }
     38   }
     39   FX_Free(m_pBuffer);
     40   m_pBuffer = nullptr;
     41 }
     42 
     43 void CPDF_Color::ReleaseColorSpace() {
     44   if (!m_pCS)
     45     return;
     46 
     47   CPDF_Document* pDoc = m_pCS->GetDocument();
     48   if (!pDoc)
     49     return;
     50 
     51   auto* pPageData = pDoc->GetPageData();
     52   if (pPageData)
     53     pPageData->ReleaseColorSpace(m_pCS->GetArray());
     54 
     55   m_pCS = nullptr;
     56 }
     57 
     58 bool CPDF_Color::IsPatternInternal() const {
     59   return m_pCS->GetFamily() == PDFCS_PATTERN;
     60 }
     61 
     62 void CPDF_Color::SetColorSpace(CPDF_ColorSpace* pCS) {
     63   if (m_pCS == pCS) {
     64     if (!m_pBuffer)
     65       m_pBuffer = pCS->CreateBuf();
     66 
     67     ReleaseColorSpace();
     68     m_pCS = pCS;
     69     return;
     70   }
     71   ReleaseBuffer();
     72   ReleaseColorSpace();
     73 
     74   m_pCS = pCS;
     75   if (pCS) {
     76     m_pBuffer = pCS->CreateBuf();
     77     pCS->GetDefaultColor(m_pBuffer);
     78   }
     79 }
     80 
     81 void CPDF_Color::SetValue(const float* comps) {
     82   if (!m_pBuffer)
     83     return;
     84   if (!IsPatternInternal())
     85     memcpy(m_pBuffer, comps, m_pCS->CountComponents() * sizeof(float));
     86 }
     87 
     88 void CPDF_Color::SetValue(CPDF_Pattern* pPattern,
     89                           const float* comps,
     90                           uint32_t ncomps) {
     91   if (ncomps > kMaxPatternColorComps)
     92     return;
     93 
     94   if (!IsPattern()) {
     95     FX_Free(m_pBuffer);
     96     m_pCS = CPDF_ColorSpace::GetStockCS(PDFCS_PATTERN);
     97     m_pBuffer = m_pCS->CreateBuf();
     98   }
     99 
    100   CPDF_DocPageData* pDocPageData = nullptr;
    101   PatternValue* pvalue = reinterpret_cast<PatternValue*>(m_pBuffer);
    102   if (pvalue->m_pPattern) {
    103     pDocPageData = pvalue->m_pPattern->document()->GetPageData();
    104     pDocPageData->ReleasePattern(pvalue->m_pPattern->pattern_obj());
    105   }
    106   pvalue->m_nComps = ncomps;
    107   pvalue->m_pPattern = pPattern;
    108   if (ncomps)
    109     memcpy(pvalue->m_Comps, comps, ncomps * sizeof(float));
    110 
    111   pvalue->m_pCountedPattern = nullptr;
    112   if (pPattern) {
    113     if (!pDocPageData)
    114       pDocPageData = pPattern->document()->GetPageData();
    115 
    116     pvalue->m_pCountedPattern =
    117         pDocPageData->FindPatternPtr(pPattern->pattern_obj());
    118   }
    119 }
    120 
    121 void CPDF_Color::Copy(const CPDF_Color* pSrc) {
    122   ReleaseBuffer();
    123   ReleaseColorSpace();
    124   m_pCS = pSrc->m_pCS;
    125   if (!m_pCS)
    126     return;
    127 
    128   CPDF_Document* pDoc = m_pCS->GetDocument();
    129   CPDF_Array* pArray = m_pCS->GetArray();
    130   if (pDoc && pArray) {
    131     m_pCS = pDoc->GetPageData()->GetCopiedColorSpace(pArray);
    132     if (!m_pCS)
    133       return;
    134   }
    135   m_pBuffer = m_pCS->CreateBuf();
    136   memcpy(m_pBuffer, pSrc->m_pBuffer, m_pCS->GetBufSize());
    137   if (!IsPatternInternal())
    138     return;
    139 
    140   PatternValue* pValue = reinterpret_cast<PatternValue*>(m_pBuffer);
    141   CPDF_Pattern* pPattern = pValue->m_pPattern;
    142   if (!pPattern)
    143     return;
    144 
    145   pValue->m_pPattern = pPattern->document()->GetPageData()->GetPattern(
    146       pPattern->pattern_obj(), false, pPattern->parent_matrix());
    147 }
    148 
    149 bool CPDF_Color::GetRGB(int* R, int* G, int* B) const {
    150   if (!m_pCS || !m_pBuffer)
    151     return false;
    152 
    153   float r = 0.0f;
    154   float g = 0.0f;
    155   float b = 0.0f;
    156   if (!m_pCS->GetRGB(m_pBuffer, &r, &g, &b))
    157     return false;
    158 
    159   *R = static_cast<int32_t>(r * 255 + 0.5f);
    160   *G = static_cast<int32_t>(g * 255 + 0.5f);
    161   *B = static_cast<int32_t>(b * 255 + 0.5f);
    162   return true;
    163 }
    164 
    165 CPDF_Pattern* CPDF_Color::GetPattern() const {
    166   if (!m_pBuffer || !IsPatternInternal())
    167     return nullptr;
    168 
    169   PatternValue* pvalue = reinterpret_cast<PatternValue*>(m_pBuffer);
    170   return pvalue->m_pPattern;
    171 }
    172