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
CPDF_Color()14 CPDF_Color::CPDF_Color() {}
15
~CPDF_Color()16 CPDF_Color::~CPDF_Color() {
17 ReleaseBuffer();
18 ReleaseColorSpace();
19 }
20
IsPattern() const21 bool CPDF_Color::IsPattern() const {
22 return m_pCS && IsPatternInternal();
23 }
24
ReleaseBuffer()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
ReleaseColorSpace()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
IsPatternInternal() const58 bool CPDF_Color::IsPatternInternal() const {
59 return m_pCS->GetFamily() == PDFCS_PATTERN;
60 }
61
SetColorSpace(CPDF_ColorSpace * pCS)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
SetValue(const float * comps)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
SetValue(CPDF_Pattern * pPattern,const float * comps,uint32_t ncomps)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
Copy(const CPDF_Color * pSrc)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
GetRGB(int * R,int * G,int * B) const149 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
GetPattern() const165 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