From 1197c505672a17b2abbc8cda0df5bce89847f28d Mon Sep 17 00:00:00 2001 From: Michael Uleysky Date: Thu, 10 Dec 2015 14:28:16 +1000 Subject: [PATCH] Gmt module: Add structure and function for representation of font parameters. --- modules/gmt/modgmt.cpp | 3 + modules/gmt/modgmt_func.h | 121 ++++++++++++++++++++++++++++++++- modules/gmt/modgmt_objects.cpp | 46 +++++++++++++ modules/gmt/modgmt_objects.h | 9 +++ modules/gmt/modgmt_structs.h | 68 ++++++++++++++++++ 5 files changed, 246 insertions(+), 1 deletion(-) diff --git a/modules/gmt/modgmt.cpp b/modules/gmt/modgmt.cpp index 558e382..f35a639 100644 --- a/modules/gmt/modgmt.cpp +++ b/modules/gmt/modgmt.cpp @@ -17,6 +17,7 @@ int gmt_module_init(void* p) if(0!=ret) return ret; gmt_projection::FillProjNames(); + if(!gmt_font::FillFontNames()) return 1; RegisterFunction("GMT_Header",GMT_Header); RegisterFunction("GMT_Footer",GMT_Footer); @@ -26,6 +27,7 @@ int gmt_module_init(void* p) RegisterFunction("GET",Get); RegisterFunction("GET",Get); RegisterFunction("GET",Get); + RegisterFunction("GET",Get); RegisterFunction("GET",Get); RegisterFunction("Coord",GMT_Type); @@ -37,5 +39,6 @@ int gmt_module_init(void* p) RegisterFunction("ColorHSV",GMT_ColorHSV); RegisterFunction("ColorCMYK",GMT_ColorCMYK); RegisterFunction("Pen",GMT_Type); + RegisterFunction("Font",GMT_Type); return 0; } diff --git a/modules/gmt/modgmt_func.h b/modules/gmt/modgmt_func.h index a3c0345..6a713aa 100644 --- a/modules/gmt/modgmt_func.h +++ b/modules/gmt/modgmt_func.h @@ -254,7 +254,9 @@ typedef TypeStorage::Base2Type Base2Dash; // Definitions for ObjectGMTPen template<> class TypeStorage: public gTypeStorage {}; typedef TypeStorage::Base2Type Base2Pen; - +// Definitions for ObjectGMTFont +template<> class TypeStorage: public gTypeStorage {}; +typedef TypeStorage::Base2Type Base2Font; // Conversion from List to GMTRegion /* @@ -1204,6 +1206,123 @@ class Convert2Struct } }; + +// Converting List to GMTFont +/* +Input: +1) One argument, Font. Return copy of this argument. +2) One argument, list. Recursively calling GMT_Font. +3) Pairs list. Names are size (s), family (f) and color(c). Default values is 12pt for size, Times-Roman for family and black for color. +If pair with name font exists in list, when recursively calling GMT_Font on the value of this parameter, when modify it with specified parameters. +If argument with type Font exists in list, when copy it and modify with specified parameters. +Instead of color unnamed parameter with Color type may be used. +4) One numeric argument, interprets as size of Times-Roman black font. +5) One string argument, interprets as [size][,family][,color] or [family][,color]. +6) Two arguments, interprets as size and family of black font. +7) Three arguments, interprets as size, family and color. +*/ + +template<> +class Convert2Struct +{ + public: + + struct gmt_font operator()(const ObjectList* input, bool* issuc) const + { + struct gmt_font f; + auto size=input->Size(); + + if(1==size) // Cases 1, 2, 4 and 5 + { + Base2Font font(input,0); + bool suc=true; + f=font(&suc); + if(!suc) goto fail; // Conversion failed + return f; + } + + // Case 3 + { + bool casevalid=false; + bool upd; + { + SearchParameter updarg(input,"font"); + bool suc=true; + f=updarg(&upd,&suc); + if(upd && !suc) goto fail; // Conversion failed or too many arguments + } + + if(!upd) + { + // default font is Times-Roman, 12pt, black + f.size=gmt_font::default_size; + f.color.Convert(0); + f.family=gmt_font::default_family; + } + + // Size + { + BaseM2Width s(input,"s","size"); + if(s.Exist()) + { + bool suc=true; + f.size=s(&suc); + if(!suc) goto fail; // Parsing error + casevalid=true; + } + } + + // Family + { + SearchParameter family(input,"family","f"); + if(family.Exist()) + { + bool suc=true; + f.family=family(&suc); + if(!suc) goto fail; // Parsing error + casevalid=true; + } + } + + // Color + { + SearchParameter color(input,"color","c"); + if(color.Exist()) + { + bool suc=true; + f.color=color(&suc); + if(!suc) goto fail; // Parsing error + casevalid=true; + } + } + + if(casevalid || upd) return f; // Pen created or updated + } + + // Case 6 and 7 + if(2==size || 3==size) + { + Base2Width s(input,0); + Base2String fam(input,1); + Base2Color c(input,2); + bool suc=true; + if(s && fam) + { + f.size=s(&suc); + f.family=fam(&suc); + } + else goto fail; // Something wrong + if(c) f.color=c(&suc); + if(!suc) goto fail; // Something wrong + return f; + } + + fail: + *issuc=false; + return f; // Something go wrong + } +}; + // Template for generating GMTObject from ObjectList template ObjectBase* GMT_Type(const ObjectList* input) diff --git a/modules/gmt/modgmt_objects.cpp b/modules/gmt/modgmt_objects.cpp index 4c86cfa..f66166b 100644 --- a/modules/gmt/modgmt_objects.cpp +++ b/modules/gmt/modgmt_objects.cpp @@ -6,6 +6,7 @@ template<> const std::string ObjectGMTProjection::type="GMTProjection"; 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"; std::map gmt_projection::projnames; @@ -48,6 +49,51 @@ void gmt_projection::FillProjNames() projnames["cylindrical stereographic"]=CYL_STERE; } +bool gmt_font::FillFontNames() +{ + families.insert("Helvetica"); + families.insert("Helvetica-Bold"); + families.insert("Helvetica-Oblique"); + families.insert("Helvetica-BoldOblique"); + families.insert("Times-Roman"); + families.insert("Times-Bold"); + families.insert("Times-Italic"); + families.insert("Times-BoldItalic"); + families.insert("Courier"); + families.insert("Courier-Bold"); + families.insert("Courier-Oblique"); + families.insert("Courier-BoldOblique"); + families.insert("Symbol"); + families.insert("AvantGarde-Book"); + families.insert("AvantGarde-BookOblique"); + families.insert("AvantGarde-Demi"); + families.insert("AvantGarde-DemiOblique"); + families.insert("Bookman-Demi"); + families.insert("Bookman-DemiItalic"); + families.insert("Bookman-Light"); + families.insert("Bookman-LightItalic"); + families.insert("Helvetica-Narrow"); + families.insert("Helvetica-Narrow-Bold"); + families.insert("Helvetica-Narrow-Oblique"); + families.insert("Helvetica-Narrow-BoldOblique"); + families.insert("NewCenturySchlbk-Roman"); + families.insert("NewCenturySchlbk-Italic"); + families.insert("NewCenturySchlbk-Bold"); + families.insert("NewCenturySchlbk-BoldItalic"); + families.insert("Palatino-Roman"); + families.insert("Palatino-Italic"); + families.insert("Palatino-Bold"); + families.insert("Palatino-BoldItalic"); + families.insert("ZapfChancery-MediumItalic"); + families.insert("ZapfDingbats"); + + default_family="Times-Roman"; + return true; +} + const double gmt_projection::default_width=10.0; const double gmt_pen::default_width=1.0; const double gmt_dash::default_width=gmt_pen::default_width; +const double gmt_font::default_size=12.0; +std::string gmt_font::default_family; +std::set gmt_font::families; diff --git a/modules/gmt/modgmt_objects.h b/modules/gmt/modgmt_objects.h index a232194..f6c9f52 100644 --- a/modules/gmt/modgmt_objects.h +++ b/modules/gmt/modgmt_objects.h @@ -118,6 +118,15 @@ template<> inline ObjectBase* ObjectGMTPen::OGet(const std::string& name) const return 0; } +// GMTFont +typedef ObjectGMTClass ObjectGMTFont; +template<> inline ObjectBase* ObjectGMTFont::OGet(const std::string& name) const +{ + if("s"==name || "size"==name) return new ObjectReal(s.size); + if("f"==name || "family"==name)return new ObjectString(s.family); + if("c"==name || "color"==name) return new ObjectGMTColor(s.color); + return 0; +} // GMTLayer class ObjectGMTLayer: public ObjectBase diff --git a/modules/gmt/modgmt_structs.h b/modules/gmt/modgmt_structs.h index 40cefe1..d7c0574 100644 --- a/modules/gmt/modgmt_structs.h +++ b/modules/gmt/modgmt_structs.h @@ -727,4 +727,72 @@ struct gmt_pen: public gmt_struct return true; } }; + + +// Font +struct gmt_font: public gmt_struct +{ + double size; + struct gmt_color color; + std::string family; + static std::string default_family; + static std::set families; + static const double default_size; + + std::string Value() const {return ToString(size)+"p,"+family+","+color.Value();} + + // Interpret one numeric argument as size of default black font + bool Convert(double in) + { + Value2Width s(in); + bool suc=true; + color.Convert(0); // Black + size=s(&suc); + family=default_family; + return suc; + } + + // Convert from string + bool Convert(const std::string& str) + { + WordList::const_iterator ci; + WordList wl=Split(str,",",true); + + // Defaults + size=default_size; + family=default_family; + color.Convert(0); // Black + + if(wl.size()>3) return false; // String is [size][,family][,color] or [family][,color] + ci=wl.begin(); + if(wl.end()!=ci && 0!=ci->size()) + { + Value2Width s(*ci); + bool suc=true; + size=s(&suc); + if(!suc) // Parse error. check if argument is font name + { + if(0==families.count(*ci)) return false; // No, argument is not allowed font name + family=*ci; + if(wl.size()>2) return false; // If first word is font name, then words count is 1 or 2. + goto read_color; + } + } + if(wl.end()!=ci) ci++; + if(wl.end()!=ci && 0!=ci->size()) + { + if(0==families.count(*ci)) return false; // Argument is not allowed font name + family=*ci; + } + read_color: + if(wl.end()!=ci) ci++; + if(wl.end()!=ci && 0!=ci->size()) + { + if(!color.Convert(*ci)) return false; // Parse error + } + return true; + } + + static bool FillFontNames(); +}; #endif