|
|
|
@ -44,6 +44,88 @@ class DoubleConv<ObjectString>
|
|
|
|
|
}; |
|
|
|
|
typedef Base2Something<DoubleConv,ObjectReal,ObjectInt,ObjectString> Base2Double; |
|
|
|
|
|
|
|
|
|
// Additional policies to let GetDouble work with Base2Double
|
|
|
|
|
// We use rational representation of floating point number, because double type values not allowed as template parameter
|
|
|
|
|
template<int32_t num=0, uint32_t denum=1> |
|
|
|
|
class PDefaultVal |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
double operator()() const {return static_cast<double>(num)/denum;} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
class PMultiInputNames {}; |
|
|
|
|
|
|
|
|
|
// Special case for default value policy. This policy mast be last in policies list.
|
|
|
|
|
template<int32_t num, uint32_t denum> |
|
|
|
|
class GetDouble<PDefaultVal<num,denum> >: public Base2Double |
|
|
|
|
{ |
|
|
|
|
PDefaultVal<num,denum> p; |
|
|
|
|
public: |
|
|
|
|
GetDouble(GetDouble&&) = delete; |
|
|
|
|
GetDouble(GetDouble&) = delete; |
|
|
|
|
GetDouble() = delete; |
|
|
|
|
GetDouble(const ObjectBase* arg):Base2Double(arg) {}; |
|
|
|
|
GetDouble(const ObjectList* input, const std::string& name):Base2Double(input,name){}; |
|
|
|
|
GetDouble(const ObjectList* input, const ObjectList::ListValues::size_type i):Base2Double(input,i){}; |
|
|
|
|
double operator()(bool* suc) const |
|
|
|
|
{ |
|
|
|
|
if(Exist()) return Base2Double::operator()(suc); |
|
|
|
|
else return p(); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// Special case for multiple input names policy. This policy mast be last in policies list.
|
|
|
|
|
template<> |
|
|
|
|
class GetDouble<PMultiInputNames> |
|
|
|
|
{ |
|
|
|
|
bool exist; |
|
|
|
|
bool ok; |
|
|
|
|
double val; |
|
|
|
|
public: |
|
|
|
|
GetDouble(GetDouble&&) = delete; |
|
|
|
|
GetDouble(GetDouble&) = delete; |
|
|
|
|
GetDouble() = delete; |
|
|
|
|
template<class... Args> |
|
|
|
|
GetDouble(const ObjectList* input, const std::string& name, Args... args):GetDouble(input,args...) |
|
|
|
|
{ |
|
|
|
|
Base2Double a(input,name); |
|
|
|
|
if(exist && a.Exist()) ok=false; |
|
|
|
|
else if(a.Exist()) |
|
|
|
|
{ |
|
|
|
|
exist=true; |
|
|
|
|
ok=true; |
|
|
|
|
val=a(&ok); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
GetDouble(const ObjectList* input, const std::string& name) |
|
|
|
|
{ |
|
|
|
|
Base2Double a(input,name); |
|
|
|
|
exist=a.Exist(); |
|
|
|
|
ok=true; |
|
|
|
|
if(exist) val=a(&ok); |
|
|
|
|
} |
|
|
|
|
double operator()(bool* suc) const |
|
|
|
|
{ |
|
|
|
|
if(!ok || !exist) *suc=false; |
|
|
|
|
return val; |
|
|
|
|
} |
|
|
|
|
bool Exist() const {return exist;} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// Bottom of recursion
|
|
|
|
|
template<> |
|
|
|
|
class GetDouble<>: public Base2Double |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
GetDouble(GetDouble&&) = delete; |
|
|
|
|
GetDouble(GetDouble&) = delete; |
|
|
|
|
GetDouble() = delete; |
|
|
|
|
GetDouble(const ObjectBase* arg):Base2Double(arg) {}; |
|
|
|
|
GetDouble(const ObjectList* input, const std::string& name):Base2Double(input,name){}; |
|
|
|
|
GetDouble(const ObjectList* input, const ObjectList::ListValues::size_type i):Base2Double(input,i){}; |
|
|
|
|
double operator()(bool* suc) const {return Base2Double::operator()(suc);} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
// Converting Int, Real or String to GMTCoord
|
|
|
|
|
template<class O> class CoordConv |
|
|
|
|
{ |
|
|
|
@ -829,6 +911,215 @@ class ProjConv<ObjectGMTProjection>
|
|
|
|
|
}; |
|
|
|
|
typedef Base2Something<ProjConv,ObjectList,ObjectGMTProjection> Base2Proj; |
|
|
|
|
|
|
|
|
|
// Helper types
|
|
|
|
|
typedef GetDouble<PMin<0>,PMax<255>,PDefaultVal<>> Base2RGB; |
|
|
|
|
typedef GetDouble<PMin<0>,PMax<360>,PDefaultVal<>> Base2Hue; |
|
|
|
|
typedef GetDouble<PMin<0>,PMax<1>,PDefaultVal<>> Base2SV; |
|
|
|
|
typedef GetDouble<PMin<0>,PMax<100>,PDefaultVal<>> Base2CMYK; |
|
|
|
|
typedef GetDouble<PMin<0>,PMax<100>,PDefaultVal<>> Base2Transp; |
|
|
|
|
|
|
|
|
|
typedef GetDouble<PMin<0>,PMax<255>,PMultiInputNames> BaseM2RGB; |
|
|
|
|
typedef GetDouble<PMin<0>,PMax<360>,PMultiInputNames> BaseM2Hue; |
|
|
|
|
typedef GetDouble<PMin<0>,PMax<1>,PMultiInputNames> BaseM2SV; |
|
|
|
|
typedef GetDouble<PMin<0>,PMax<100>,PMultiInputNames> BaseM2CMYK; |
|
|
|
|
typedef GetDouble<PMin<0>,PMax<100>,PMultiInputNames> BaseM2Transp; |
|
|
|
|
|
|
|
|
|
// Converting List to GMTColor
|
|
|
|
|
template<class O> class ColorConv |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
struct gmt_color operator()(const O* o, bool* issuc) const |
|
|
|
|
{ |
|
|
|
|
struct gmt_color c; |
|
|
|
|
if(!c.Convert(o->Value())) *issuc=false; |
|
|
|
|
return c; |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
// Special case is GMTColor
|
|
|
|
|
template<> |
|
|
|
|
class ColorConv<ObjectGMTColor> |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
struct gmt_color operator()(const ObjectGMTColor* o, bool* suc) const {return o->Data();} |
|
|
|
|
}; |
|
|
|
|
typedef Base2Something<ColorConv,ObjectList,ObjectString,ObjectReal,ObjectInt,ObjectGMTColor> Base2Color; |
|
|
|
|
// Conversion from List
|
|
|
|
|
template<> |
|
|
|
|
class ColorConv<ObjectList> |
|
|
|
|
{ |
|
|
|
|
public: |
|
|
|
|
// Cases see in description of GMT_Color function
|
|
|
|
|
struct gmt_color operator()(const ObjectList* input, bool* issuc) const |
|
|
|
|
{ |
|
|
|
|
struct gmt_color c; |
|
|
|
|
auto size=input->Size(); |
|
|
|
|
|
|
|
|
|
if(1==size) // Cases 1, 2 and 4
|
|
|
|
|
{ |
|
|
|
|
Base2Color a(input,0); |
|
|
|
|
bool suc=true; |
|
|
|
|
c=a(&suc); |
|
|
|
|
if(suc) return c; |
|
|
|
|
goto fail; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Case 3
|
|
|
|
|
{ |
|
|
|
|
bool upd=false; |
|
|
|
|
bool cmodset=false; |
|
|
|
|
|
|
|
|
|
// Update case, arguments list contains parameter with type GMTColor.
|
|
|
|
|
for(ObjectList::ListValues::size_type i=0;i<size;i++) |
|
|
|
|
{ |
|
|
|
|
OBType<ObjectGMTColor> color(input->At(i)); |
|
|
|
|
if(color) |
|
|
|
|
{ |
|
|
|
|
if(upd) goto fail; // Only one color in list allowed
|
|
|
|
|
c=color->Data(); |
|
|
|
|
upd=true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Update case, arguments list contains parameter color and this parameter is color.
|
|
|
|
|
{ |
|
|
|
|
Base2Color col(input,"color"); |
|
|
|
|
if(col.Exist()) |
|
|
|
|
{ |
|
|
|
|
if(upd) goto fail; // Already have color to update
|
|
|
|
|
bool suc=true; |
|
|
|
|
struct gmt_color cs=col(&suc); |
|
|
|
|
if(suc) |
|
|
|
|
{ |
|
|
|
|
upd=true; |
|
|
|
|
c=cs; |
|
|
|
|
} |
|
|
|
|
else goto fail; // Parse error
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if(!upd) |
|
|
|
|
{ |
|
|
|
|
// default color is black
|
|
|
|
|
c.transparency=0; |
|
|
|
|
c.model=gmt_color::GRAY; |
|
|
|
|
c.gray=0.0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
BaseM2Transp t(input,"t","transp","transparency"); |
|
|
|
|
if(t.Exist()) |
|
|
|
|
{ |
|
|
|
|
bool suc=true; |
|
|
|
|
c.transparency=t(&suc); |
|
|
|
|
if(!suc) goto fail; // Parsing error
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// GRAY
|
|
|
|
|
{ |
|
|
|
|
BaseM2RGB g(input,"gray","grey"); |
|
|
|
|
if(g.Exist()) |
|
|
|
|
{ |
|
|
|
|
if(cmodset) goto fail; // Model already set
|
|
|
|
|
bool suc=true; |
|
|
|
|
c.model=gmt_color::GRAY; |
|
|
|
|
c.gray=g(&suc); // Update mode ignored in this case
|
|
|
|
|
if(!suc) goto fail; // Parsing error
|
|
|
|
|
cmodset=true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// RGB
|
|
|
|
|
{ |
|
|
|
|
BaseM2RGB r(input,"r","red"), g(input,"g","green"), b(input,"b","blue"); |
|
|
|
|
if(r.Exist() || g.Exist() || b.Exist()) |
|
|
|
|
{ |
|
|
|
|
if(cmodset) goto fail; // Model already set
|
|
|
|
|
bool suc=true; |
|
|
|
|
c.ToRGB(); |
|
|
|
|
if(r.Exist()) c.r=r(&suc); |
|
|
|
|
if(g.Exist()) c.g=g(&suc); |
|
|
|
|
if(b.Exist()) c.b=b(&suc); |
|
|
|
|
if(!suc) goto fail; // Parsing error
|
|
|
|
|
cmodset=true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// HSV
|
|
|
|
|
{ |
|
|
|
|
BaseM2Hue h(input,"h","hue"); |
|
|
|
|
BaseM2SV s(input,"s","sat","saturation"), v(input,"v","val","value"); |
|
|
|
|
if(h.Exist() || s.Exist() || v.Exist()) |
|
|
|
|
{ |
|
|
|
|
if(cmodset) goto fail; // Model already set
|
|
|
|
|
bool suc=true; |
|
|
|
|
c.ToHSV(); |
|
|
|
|
if(h.Exist()) c.hue=h(&suc); |
|
|
|
|
if(s.Exist()) c.saturation=s(&suc); |
|
|
|
|
if(v.Exist()) c.value=v(&suc); |
|
|
|
|
if(!suc) goto fail; // Parsing error
|
|
|
|
|
cmodset=true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// CMYK
|
|
|
|
|
{ |
|
|
|
|
BaseM2CMYK cc(input,"c","cyan"), m(input,"m","magenta"), y(input,"y","yellow"), k(input,"k","black"); |
|
|
|
|
if(cc.Exist() || m.Exist() || y.Exist() || k.Exist()) |
|
|
|
|
{ |
|
|
|
|
if(cmodset) goto fail; // Model already set
|
|
|
|
|
bool suc=true; |
|
|
|
|
c.ToCMYK(); |
|
|
|
|
if(cc.Exist()) c.cyan=cc(&suc); |
|
|
|
|
if(m.Exist()) c.magenta=m(&suc); |
|
|
|
|
if(y.Exist()) c.yellow=y(&suc); |
|
|
|
|
if(k.Exist()) c.black=k(&suc); |
|
|
|
|
if(!suc) goto fail; // Parsing error
|
|
|
|
|
cmodset=true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
if(cmodset || upd) return c; // Color created or updated
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Case 5
|
|
|
|
|
if(3==size) |
|
|
|
|
{ |
|
|
|
|
Base2RGB r(input,0), g(input,1), b(input,2); |
|
|
|
|
c.model=gmt_color::RGB; |
|
|
|
|
bool suc=true; |
|
|
|
|
if(r && g && b) |
|
|
|
|
{ |
|
|
|
|
c.r=r(&suc); |
|
|
|
|
c.g=g(&suc); |
|
|
|
|
c.b=b(&suc); |
|
|
|
|
if(!suc) goto fail; // Parsing error
|
|
|
|
|
} |
|
|
|
|
else goto fail; // Something wrong
|
|
|
|
|
return c; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Case 6
|
|
|
|
|
if(4==size) |
|
|
|
|
{ |
|
|
|
|
Base2CMYK cc(input,0), m(input,1), y(input,2), k(input,3); |
|
|
|
|
c.model=gmt_color::CMYK; |
|
|
|
|
bool suc=true; |
|
|
|
|
if(cc && m && y && k) |
|
|
|
|
{ |
|
|
|
|
c.cyan=cc(&suc); |
|
|
|
|
c.magenta=m(&suc); |
|
|
|
|
c.yellow=y(&suc); |
|
|
|
|
c.black=k(&suc); |
|
|
|
|
if(!suc) goto fail; // Parsing error
|
|
|
|
|
} |
|
|
|
|
else goto fail; // Something wrong
|
|
|
|
|
return c; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fail: |
|
|
|
|
*issuc=false; |
|
|
|
|
return c; // Something go wrong
|
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Input is one argument, Int, Real, String or GMTCoord. |
|
|
|
@ -886,3 +1177,94 @@ ObjectBase* GMT_Projection(const ObjectList* input)
|
|
|
|
|
if(suc) return new ObjectGMTProjection(p); |
|
|
|
|
else return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
Input: |
|
|
|
|
1) One argument, Color. Return copy of this argument. |
|
|
|
|
2) One argument, list. Recursively calling GMT_Color. |
|
|
|
|
3) Pairs list. Names are gray (grey), r(red),g(green),b(blue), h(hue),s(sat,saturation),v(value), c(cyan),m(magenta),y(yellow),k(black) and t(transp,transparency). |
|
|
|
|
The different color models can't be mixed. |
|
|
|
|
Gray, r, g, b are doubles in the range 0-255, h is double in the range 0-360, s and v are doubles in the range 0-1 and c, m, y, k and transparency are doubles in the range 0-100. Default value for all parameters is 0. |
|
|
|
|
If pair with name color exists in list, when recursively calling GMT_Color on the value of this parameter, when modify it with specified parameters. |
|
|
|
|
If argument with type Color exists in list, when copy it and modify with specified parameters. In both cases color model changing as specified by parameters. |
|
|
|
|
4) One argument, interprets as gray. |
|
|
|
|
5) Three arguments, interprets as r, g, b. |
|
|
|
|
6) Four arguments, interprets as c, m, y, k. |
|
|
|
|
Transparency or HSV model can be set only in form 3. |
|
|
|
|
*/ |
|
|
|
|
ObjectBase* GMT_Color(const ObjectList* input) |
|
|
|
|
{ |
|
|
|
|
bool suc=true; |
|
|
|
|
struct gmt_color c=ColorConv<ObjectList>()(input,&suc); |
|
|
|
|
if(suc) return new ObjectGMTColor(c); |
|
|
|
|
else return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ObjectBase* GMT_ColorGray(const ObjectList* input) |
|
|
|
|
{ |
|
|
|
|
struct gmt_color c; |
|
|
|
|
bool suc=true; |
|
|
|
|
Base2RGB g(input,0); |
|
|
|
|
Base2Transp t(input,1); |
|
|
|
|
|
|
|
|
|
c.model=gmt_color::GRAY; |
|
|
|
|
c.gray=g(&suc); |
|
|
|
|
c.transparency=t(&suc); |
|
|
|
|
|
|
|
|
|
if(suc) return new ObjectGMTColor(c); |
|
|
|
|
else return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ObjectBase* GMT_ColorRGB(const ObjectList* input) |
|
|
|
|
{ |
|
|
|
|
struct gmt_color c; |
|
|
|
|
bool suc=true; |
|
|
|
|
Base2RGB r(input,0),g(input,1),b(input,2); |
|
|
|
|
Base2Transp t(input,3); |
|
|
|
|
|
|
|
|
|
c.model=gmt_color::RGB; |
|
|
|
|
c.r=r(&suc); |
|
|
|
|
c.g=g(&suc); |
|
|
|
|
c.b=b(&suc); |
|
|
|
|
c.transparency=t(&suc); |
|
|
|
|
|
|
|
|
|
if(suc) return new ObjectGMTColor(c); |
|
|
|
|
else return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ObjectBase* GMT_ColorHSV(const ObjectList* input) |
|
|
|
|
{ |
|
|
|
|
struct gmt_color c; |
|
|
|
|
bool suc=true; |
|
|
|
|
Base2Hue h(input,0); |
|
|
|
|
Base2SV s(input,1),v(input,2); |
|
|
|
|
Base2Transp t(input,3); |
|
|
|
|
|
|
|
|
|
c.model=gmt_color::HSV; |
|
|
|
|
c.hue=h(&suc); |
|
|
|
|
c.saturation=s(&suc); |
|
|
|
|
c.value=v(&suc); |
|
|
|
|
c.transparency=t(&suc); |
|
|
|
|
|
|
|
|
|
if(suc) return new ObjectGMTColor(c); |
|
|
|
|
else return 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
ObjectBase* GMT_ColorCMYK(const ObjectList* input) |
|
|
|
|
{ |
|
|
|
|
struct gmt_color c; |
|
|
|
|
bool suc=true; |
|
|
|
|
Base2CMYK cyan(input,0),m(input,1),y(input,2),k(input,3); |
|
|
|
|
Base2Transp t(input,4); |
|
|
|
|
|
|
|
|
|
c.model=gmt_color::CMYK; |
|
|
|
|
c.cyan=cyan(&suc); |
|
|
|
|
c.magenta=m(&suc); |
|
|
|
|
c.yellow=y(&suc); |
|
|
|
|
c.black=k(&suc); |
|
|
|
|
c.transparency=t(&suc); |
|
|
|
|
|
|
|
|
|
if(suc) return new ObjectGMTColor(c); |
|
|
|
|
else return 0; |
|
|
|
|
} |
|
|
|
|