diff --git a/modules/gmt/modgmt.cpp b/modules/gmt/modgmt.cpp index f35a639..5896623 100644 --- a/modules/gmt/modgmt.cpp +++ b/modules/gmt/modgmt.cpp @@ -40,5 +40,6 @@ int gmt_module_init(void* p) RegisterFunction("ColorCMYK",GMT_ColorCMYK); RegisterFunction("Pen",GMT_Type); RegisterFunction("Font",GMT_Type); + RegisterFunction("Shift",GMT_LayerShift); return 0; } diff --git a/modules/gmt/modgmt_func.cpp b/modules/gmt/modgmt_func.cpp index b3c2b05..7873dc2 100644 --- a/modules/gmt/modgmt_func.cpp +++ b/modules/gmt/modgmt_func.cpp @@ -77,3 +77,57 @@ ObjectBase* GMT_ColorCMYK(const ObjectList* input) if(suc) return new ObjectGMTColor(c); else return 0; } + +// Shifting layer +/* +Input: +1) Three arguments, first is Layer, second and third are double. Interprets as new absolute position in cm. +2) Pairs list. Names are l (layer), x, y, xrel (xr), yrel (yr). Pair with name l may be absent, in this case search in list and using as layer object with ObjectGMTLayer type. x and y are absolute positions in cm, xrel and yrel are shift from current position. x (y) and xrel (yrel) are mutually exlusive, but x (y) and yrel (xrel) can be used simultaneously. If position for some axis is absent, then this position is unchanged. +*/ +ObjectBase* GMT_LayerShift(const ObjectList* input) +{ + auto size=input->Size(); + struct gmt_layer layer; + + // Case 1 + if(3==size) + { + Base2Layer l(input,0); + Base2Double x(input,1), y(input,2); + bool suc=true; + layer=l(&suc); + if(!suc) goto case2; + layer.shiftx=x(&suc); + layer.shifty=y(&suc); + if(!suc) goto case2; + return new ObjectGMTLayer(layer); + } + + case2: + + // Search layer for shifting + { + SearchParameter original(input,"layer","l"); + bool suc=true; + layer=original(&suc); + if(!suc) goto fail; // Conversion failed or too many arguments + } + // Do shift + { + BaseM2Double xr(input,"xrel","xr"), yr(input,"yrel","yr"); + Base2Double x(input,"x"), y(input,"y"); + bool suc=true; + // Check duplicate parameters + if( ( x.Exist() && xr.Exist() ) || ( y.Exist() && yr.Exist() ) ) goto fail; + if(x.Exist()) layer.shiftx=x(&suc); + if(y.Exist()) layer.shifty=y(&suc); + if(xr.Exist()) layer.shiftx+=x(&suc); + if(yr.Exist()) layer.shifty+=y(&suc); + if(!suc) goto fail; + } + + return new ObjectGMTLayer(layer); + + fail: + return 0; +} diff --git a/modules/gmt/modgmt_func.h b/modules/gmt/modgmt_func.h index 28f36b3..578d6c6 100644 --- a/modules/gmt/modgmt_func.h +++ b/modules/gmt/modgmt_func.h @@ -9,6 +9,7 @@ ObjectBase* GMT_ColorGray(const ObjectList* input); ObjectBase* GMT_ColorRGB(const ObjectList* input); ObjectBase* GMT_ColorHSV(const ObjectList* input); ObjectBase* GMT_ColorCMYK(const ObjectList* input); +ObjectBase* GMT_LayerShift(const ObjectList* input); // Extension of OBTypeM template for easy work with lists template class Func, class... O> @@ -260,6 +261,9 @@ typedef TypeStorage::Base2Type Base2Pen; // Definitions for ObjectGMTFont template<> class TypeStorage: public gTypeStorage {}; typedef TypeStorage::Base2Type Base2Font; +// Definitions for ObjectGMTLayer +template<> class TypeStorage: public gTypeStorage {}; +typedef TypeStorage::Base2Type Base2Layer; // Conversion from List to GMTRegion /* @@ -1336,4 +1340,7 @@ ObjectBase* GMT_Type(const ObjectList* input) else return 0; } +// Shift position of layer +ObjectBase* GMT_LayerShift(const ObjectList* input); + #endif diff --git a/modules/gmt/modgmt_objects.cpp b/modules/gmt/modgmt_objects.cpp index f66166b..125d65a 100644 --- a/modules/gmt/modgmt_objects.cpp +++ b/modules/gmt/modgmt_objects.cpp @@ -7,6 +7,30 @@ template<> const std::string ObjectGMTColor::type="GMTColor"; template<> const std::string ObjectGMTDash::type="GMTDash"; template<> const std::string ObjectGMTPen::type="GMTPen"; template<> const std::string ObjectGMTFont::type="GMTFont"; +template<> const std::string ObjectGMTLayer::type="GMTLayer"; + +template<> const int8_t* ObjectGMTLayer::Blob(size_t* size) const +{ + if(s.Shifted()) + { + std::string b="V "+ToString(cm2GMT(s.shiftx))+" "+ToString(cm2GMT(s.shifty))+" T\n"; + std::string e="U\n"; + int8_t* p=new int8_t[b.size()+s.data->size()+e.size()]; + memcpy(p,b.data(),b.size()); + memcpy(p+b.size(),s.data->data(),s.data->size()); + memcpy(p+b.size()+s.data->size(),e.data(),e.size()); + return p; + } + else + { + *size=s.data->size(); + return reinterpret_cast(s.data->data()); + } +} +template<> void ObjectGMTLayer::DeallocBlob(const int8_t* ptr) const +{ + if(s.Shifted()) delete[] ptr; +} std::map gmt_projection::projnames; diff --git a/modules/gmt/modgmt_objects.h b/modules/gmt/modgmt_objects.h index f6c9f52..6e8e124 100644 --- a/modules/gmt/modgmt_objects.h +++ b/modules/gmt/modgmt_objects.h @@ -35,6 +35,8 @@ class ObjectGMTClass: public ObjectBase return true; } std::string Type() const override {return type;} + const int8_t* Blob(size_t* size) const override { *size=0; return 0; } + void DeallocBlob(const int8_t* ptr) const override {}; // Own functions ObjectBase* Get(const std::string& gname) const @@ -129,77 +131,17 @@ template<> inline ObjectBase* ObjectGMTFont::OGet(const std::string& name) const } // GMTLayer -class ObjectGMTLayer: public ObjectBase +typedef ObjectGMTClass ObjectGMTLayer; +template<> inline ObjectBase* ObjectGMTLayer::OGet(const std::string& name) const { - double shiftx,shifty; - struct gmt_projection proj; - std::string creator; - std::shared_ptr data; - - ObjectGMTLayer() {} - // This is saveable object - virtual const int8_t* Blob(size_t* size) const override - { - if(Shifted()) - { - std::string b="V "+ToString(cm2GMT(shiftx))+" "+ToString(cm2GMT(shifty))+" T\n"; - std::string e="U\n"; - int8_t* p=new int8_t[b.size()+data->size()+e.size()]; - memcpy(p,b.data(),b.size()); - memcpy(p+b.size(),data->data(),data->size()); - memcpy(p+b.size()+data->size(),e.data(),e.size()); - return p; - } - else - { - *size=data->size(); - return reinterpret_cast(data->data()); - } - } - virtual void DeallocBlob(const int8_t* ptr) const override - { - if(Shifted()) delete[] ptr; - }; - public: - // Constructor - ObjectGMTLayer(const std::string& newdata, const struct gmt_projection& newproj, const std::string& newcreator, double newshiftx=0.0, double newshifty=0.0):shiftx(newshiftx),shifty(newshifty),proj(newproj),creator(newcreator) - { - std::string* pdata=new std::string(newdata.data(),newdata.length()); // To prevent COW - data.reset(pdata); - } - // Pure virtual overrides - ObjectBase* Copy() const override - { - auto ret=new ObjectGMTLayer; - ret->shiftx=shiftx; ret->shifty=shifty; - ret->proj=proj; - ret->creator=creator; - ret->data=data; - - return ret; - } - bool Print() const override - { - COUT(NORMAL)< const int8_t* ObjectGMTLayer::Blob(size_t* size) const; +template<> void ObjectGMTLayer::DeallocBlob(const int8_t* ptr) const; - // Own functions - ObjectBase* Get(const std::string& gname) const - { - std::string name=gname; - tolower(name); - if("proj"==name || "projection"==name) return new ObjectGMTProjection(proj); - if("w"==name || "width"==name) return new ObjectReal(proj.rwidth); - if("h"==name || "height"==name) return new ObjectReal(proj.rheight); - if("shiftx"==name) return new ObjectReal(shiftx); - if("shifty"==name) return new ObjectReal(shifty); - return 0; - } - bool Shifted() const {return shiftx!=0.0 || shifty!=0.0;} -}; #endif diff --git a/modules/gmt/modgmt_structs.h b/modules/gmt/modgmt_structs.h index d7c0574..e79b6f6 100644 --- a/modules/gmt/modgmt_structs.h +++ b/modules/gmt/modgmt_structs.h @@ -795,4 +795,17 @@ struct gmt_font: public gmt_struct static bool FillFontNames(); }; + + +// Layer +struct gmt_layer: public gmt_struct +{ + double shiftx,shifty; + struct gmt_projection proj; + std::string creator; + std::shared_ptr data; + + std::string Value() const {return creator+(Shifted()?("("+ToString(shiftx)+"x"+ToString(shifty)+")"):"");} + bool Shifted() const {return shiftx!=0.0 || shifty!=0.0;} +}; #endif