COPASI API  4.16.103
CLGradientStops.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010 - 2013 by Pedro Mendes, Virginia Tech Intellectual
2 // Properties, Inc., University of Heidelberg, and The University
3 // of Manchester.
4 // All rights reserved.
5 
6 #include "CLGradientStops.h"
7 
8 #include <cmath>
9 #include <assert.h>
10 
13 
14 CLGradientStops::CLGradientStops(const CLGradientBase* pGradient, const std::map<std::string, CLRGBAColor>& colormap)
15  : mSpreadMethod(pGradient->getSpreadMethod()), mColorData(NULL), mIndex(0), mHelp(0.0)
16 {
17  size_t i, iMax = pGradient->getNumGradientStops();
18 
19  if (iMax > 0)
20  {
21  this->mColorData = new unsigned char[4 * iMax];
22  this->mIndex = 0;
23  const CLGradientStop* pStop = NULL;
24  std::string stopColor;
25  std::map<std::string, CLRGBAColor>::const_iterator pos;
26  double v = 0.0;
27  std::list<std::pair<double, unsigned int> >::reverse_iterator last;
28 
29  for (i = 0; i < iMax; ++i)
30  {
31  pStop = pGradient->getGradientStop(i);
32  assert(pStop != NULL);
33  stopColor = pStop->getStopColor();
34  assert(stopColor.find_first_not_of(" \t\n\r") != std::string::npos && stopColor != "none");
35  pos = colormap.find(stopColor);
36  assert(pos != colormap.end());
37  // offsets can only be relative values, so we ignore the absolute part
38  v = pStop->getOffset().getRelativeValue() / 100.0;
39 
40  // we cap at 0.0 and 1.0
41  if (v < 0.0)
42  {
43  v = 0.0;
44  }
45 
46  if (v > 1.0)
47  {
48  v = 1.0;
49  }
50 
51  // make sure each stop has an offset
52  // greater or equal to the preceeding
53  // offset
54  if (i != 0)
55  {
56  if (v < last->first)
57  {
58  v = last->first;
59  }
60  }
61 
62  //std::cout << "adding stop: (" << v << "," << this->mIndex << ")" << std::endl;
63  mStops.push_back(std::pair<double, unsigned int>(v, this->mIndex));
64  last = this->mStops.rbegin();
65  this->mColorData[this->mIndex] = pos->second.mR;
66  this->mColorData[++this->mIndex] = pos->second.mG;
67  this->mColorData[++this->mIndex] = pos->second.mB;
68  this->mColorData[++this->mIndex] = pos->second.mA;
69  ++this->mIndex;
70  //std::cout << "stop color: (" << (unsigned int)pos->second.r << "," << (unsigned int)pos->second.g << "," << (unsigned int)pos->second.b << "," << (unsigned int)pos->second.a << ")" << std::endl;
71  }
72  }
73  else
74  {
75  // we add one color which is completly transparent black
76  this->mColorData = new unsigned char[4];
77  this->mColorData[0] = 0;
78  this->mColorData[1] = 0;
79  this->mColorData[2] = 0;
80  this->mColorData[3] = 0;
81  this->mStops.push_back(std::pair<double, unsigned int>(0.0, 0));
82  }
83 
84  this->mBegin = this->mStops.begin();
85  this->mEnd = this->mStops.end();
86  this->mCurrentPosition = this->mBegin;
87 }
88 
90 {
91  if (this->mColorData != NULL)
92  {
93  delete[] this->mColorData;
94  }
95 }
96 
97 /**
98  * Given a relative value, this routine returns
99  * a const pointer to an rgba value that is 4 unsigned char long.
100  * If the gradient that was used to create the CLGradientStops object
101  * didn't have any gradient stops, the color that is returned is completly
102  * transparent black.
103  */
105 {
106  this->adjust_value(val);
107  this->mTmp = this->mCurrentPosition;
108 
109  //double v=this->mCurrentPosition->first;
110  if (val >= this->mCurrentPosition->first)
111  {
112  while (mTmp != mEnd && this->mTmp->first <= val)
113  {
114  ++this->mTmp;
115  //v=this->mTmp->first;
116  }
117 
118  this->mCurrentPosition = this->mTmp;
119 
120  if (this->mCurrentPosition == this->mEnd || this->mCurrentPosition->first > val)
121  {
122  --this->mCurrentPosition;
123  }
124 
125  //v=this->mCurrentPosition->first;
126  this->mIndex = this->mCurrentPosition->second;
127  this->mColor.mR = this->mColorData[this->mIndex];
128  this->mColor.mG = this->mColorData[++this->mIndex];
129  this->mColor.mB = this->mColorData[++this->mIndex];
130  this->mColor.mA = this->mColorData[++this->mIndex];
131 
132  if (this->mCurrentPosition->first < val && this->mTmp != this->mEnd)
133  {
134  // we need to calculate the exact color value from mTmp and mCurrentPosition
135  //v=this->mTmp->first;
136  mHelp = (val - this->mCurrentPosition->first) / (this->mTmp->first - this->mCurrentPosition->first);
137  this->mColor.mR += (unsigned char)(mHelp * (double)(this->mColorData[++this->mIndex] - this->mColor.mR));
138  this->mColor.mG += (unsigned char)(mHelp * (double)(this->mColorData[++this->mIndex] - this->mColor.mG));
139  this->mColor.mB += (unsigned char)(mHelp * (double)(this->mColorData[++this->mIndex] - this->mColor.mB));
140  this->mColor.mA += (unsigned char)(mHelp * (double)(this->mColorData[++this->mIndex] - this->mColor.mA));
141  }
142  }
143  else
144  {
145  // the value must be smaller than the value at the current position
146  while (this->mTmp != this->mBegin && val < this->mTmp->first)
147  {
148  //v=this->mTmp->first;
149  --this->mTmp;
150  }
151 
152  this->mCurrentPosition = this->mTmp;
153  //v=this->mCurrentPosition->first;
154  this->mIndex = this->mCurrentPosition->second;
155  this->mColor.mR = this->mColorData[this->mIndex];
156  this->mColor.mG = this->mColorData[++this->mIndex];
157  this->mColor.mB = this->mColorData[++this->mIndex];
158  this->mColor.mA = this->mColorData[++this->mIndex];
159 
160  if (val > this->mTmp->first)
161  {
162  // we need to calculate the correct value
163  ++this->mTmp;
164  //v=this->mTmp->first;
165  mHelp = (val - this->mCurrentPosition->first) / (this->mTmp->first - this->mCurrentPosition->first);
166  this->mColor.mR += (unsigned char)(mHelp * (double)(this->mColorData[++this->mIndex] - this->mColor.mR));
167  this->mColor.mG += (unsigned char)(mHelp * (double)(this->mColorData[++this->mIndex] - this->mColor.mG));
168  this->mColor.mB += (unsigned char)(mHelp * (double)(this->mColorData[++this->mIndex] - this->mColor.mB));
169  this->mColor.mA += (unsigned char)(mHelp * (double)(this->mColorData[++this->mIndex] - this->mColor.mA));
170  }
171  }
172 }
173 
175 {
176  return this->mColor;
177 }
178 
179 void CLGradientStops::adjust_value(double& value) const
180 {
181  if (value < 0.0)
182  {
183  switch (this->mSpreadMethod)
184  {
185  case CLGradientBase::PAD:
186  value = 0.0;
187  break;
188 
190  // if the part of the distance before the decimal point
191  // is devisible by 2, we just remove it
192  // otherwise, we remove it and subtract the result from
193  // 1.0
194  value = fabs(value);
195 
196  if (((unsigned int)floor(value)) % 2 != 0)
197  {
198  value = 1.0 - (value - floor(value));
199  }
200  else
201  {
202  value = value - floor(value);
203  }
204 
205  break;
206 
208  // we only need everything after the decimal point
209  // and we need to subtract from 1.0
210  value = value - floor(value);
211  break;
212  }
213  }
214  else if (value > 1.0)
215  {
216  switch (this->mSpreadMethod)
217  {
218  case CLGradientBase::PAD:
219  value = 1.0;
220  break;
221 
223 
224  // if the part of the distance before the decimal point
225  // is devisible by 2, we just remove it
226  // otherwise, we remove it and subtract the result from
227  // 1.0
228  if (((unsigned int)floor(value)) % 2 != 0)
229  {
230  value = 1.0 - (value - floor(value));
231  }
232  else
233  {
234  value = value - floor(value);
235  }
236 
237  break;
238 
240  // we only need everything after the decimal point
241  value = value - floor(value);
242  break;
243  }
244  }
245 }
unsigned int mIndex
std::list< std::pair< double, unsigned int > >::const_iterator mEnd
void adjust_value(double &value) const
void update_color(double val)
std::list< std::pair< double, unsigned int > > mStops
unsigned char mG
Definition: CLRGBAColor.h:14
unsigned char mB
Definition: CLRGBAColor.h:16
double getRelativeValue() const
unsigned char mA
Definition: CLRGBAColor.h:18
CLRGBAColor mColor
unsigned char mR
Definition: CLRGBAColor.h:12
CLGradientStop * getGradientStop(size_t i)
CLGradientBase::SPREADMETHOD mSpreadMethod
unsigned char * mColorData
size_t getNumGradientStops() const
const std::string & getStopColor() const
const CLRelAbsVector & getOffset() const
CLGradientStops(const CLGradientBase *pGradient, const std::map< std::string, CLRGBAColor > &colormap)
std::list< std::pair< double, unsigned int > >::const_iterator mCurrentPosition
const CLRGBAColor & color() const
std::list< std::pair< double, unsigned int > >::const_iterator mBegin
std::list< std::pair< double, unsigned int > >::const_iterator mTmp