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