cwSvg.h/cpp : Refactoring to make CSS more flexible, decrease size of images, and improve efficiency of write().
This commit is contained in:
parent
dc461dbe84
commit
7bb41b24e4
549
cwSvg.cpp
549
cwSvg.cpp
@ -5,6 +5,7 @@
|
|||||||
#include "cwFile.h"
|
#include "cwFile.h"
|
||||||
#include "cwSvg.h"
|
#include "cwSvg.h"
|
||||||
#include "cwText.h"
|
#include "cwText.h"
|
||||||
|
#include "cwNumericConvert.h"
|
||||||
|
|
||||||
namespace cw
|
namespace cw
|
||||||
{
|
{
|
||||||
@ -15,40 +16,40 @@ namespace cw
|
|||||||
kLineTId,
|
kLineTId,
|
||||||
kPLineTId,
|
kPLineTId,
|
||||||
kRectTId,
|
kRectTId,
|
||||||
kTextTId
|
kTextTId,
|
||||||
|
kPixelTId
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Attribute record used for CSS and SVG element attributes
|
||||||
typedef struct attr_str
|
typedef struct attr_str
|
||||||
{
|
{
|
||||||
unsigned strokeColor;
|
char* label;
|
||||||
unsigned strokeWidth;
|
char* value;
|
||||||
double strokeOpacity;
|
struct attr_str* link;
|
||||||
unsigned fillColor;
|
|
||||||
double fillOpacity;
|
|
||||||
} attr_t;
|
} attr_t;
|
||||||
|
|
||||||
|
// CSS selector record with attribute list
|
||||||
typedef struct css_str
|
typedef struct css_str
|
||||||
{
|
{
|
||||||
unsigned id;
|
char* selectorStr;
|
||||||
char* label;
|
attr_t* attrL;
|
||||||
attr_t attr;
|
|
||||||
struct css_str* link;
|
struct css_str* link;
|
||||||
} css_t;
|
} css_t;
|
||||||
|
|
||||||
|
// SVG element record
|
||||||
typedef struct ele_str
|
typedef struct ele_str
|
||||||
{
|
{
|
||||||
unsigned typeId;
|
unsigned typeId; // kLineTId,kRectPId,...
|
||||||
double x0;
|
attr_t* attrL; // element attributes (e.g. id, class)
|
||||||
|
css_t* css; // style attributes
|
||||||
|
double x0; // left,top
|
||||||
double y0;
|
double y0;
|
||||||
double x1;
|
double x1; // right,bot
|
||||||
double y1;
|
double y1;
|
||||||
char* text;
|
char* text;
|
||||||
double* xV;
|
double* xV; // poly line coords
|
||||||
double* yV;
|
double* yV;
|
||||||
unsigned yN;
|
unsigned yN;
|
||||||
attr_t attr;
|
|
||||||
unsigned cssClassId;
|
|
||||||
unsigned flags;
|
|
||||||
struct ele_str* link;
|
struct ele_str* link;
|
||||||
} ele_t;
|
} ele_t;
|
||||||
|
|
||||||
@ -62,23 +63,42 @@ namespace cw
|
|||||||
|
|
||||||
typedef struct svg_str
|
typedef struct svg_str
|
||||||
{
|
{
|
||||||
unsigned strokeColorIdx;
|
css_t* cssL; // CSS selector records
|
||||||
unsigned strokeWidth;
|
color_map_t* cmapL; // Color maps
|
||||||
unsigned fillColorIdx;
|
ele_t* eleL; // SVG elements
|
||||||
|
|
||||||
css_t* cssL;
|
double dx; // Offset new elements by this amount
|
||||||
color_map_t* cmapL;
|
double dy;
|
||||||
ele_t* eleL;
|
|
||||||
|
|
||||||
double dx;
|
ele_t* curEle; // Last SVG element allocated
|
||||||
double dy;
|
|
||||||
|
|
||||||
ele_t* curEle;
|
|
||||||
} svg_t;
|
} svg_t;
|
||||||
|
|
||||||
inline svg_t* _handleToPtr(handle_t h )
|
inline svg_t* _handleToPtr(handle_t h )
|
||||||
{ return handleToPtr<handle_t,svg_t>(h); }
|
{ return handleToPtr<handle_t,svg_t>(h); }
|
||||||
|
|
||||||
|
void _destroy_attr_list( attr_t* a )
|
||||||
|
{
|
||||||
|
while( a != nullptr )
|
||||||
|
{
|
||||||
|
attr_t* a0 = a->link;
|
||||||
|
mem::release(a->label);
|
||||||
|
mem::release(a->value);
|
||||||
|
mem::release(a);
|
||||||
|
a = a0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void _destroy_css( css_t* r )
|
||||||
|
{
|
||||||
|
if( r != nullptr )
|
||||||
|
{
|
||||||
|
mem::release(r->selectorStr);
|
||||||
|
|
||||||
|
_destroy_attr_list(r->attrL);
|
||||||
|
mem::release(r);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rc_t _destroy( struct svg_str* p )
|
rc_t _destroy( struct svg_str* p )
|
||||||
{
|
{
|
||||||
ele_t* e = p->eleL;
|
ele_t* e = p->eleL;
|
||||||
@ -88,6 +108,8 @@ namespace cw
|
|||||||
mem::release(e->text);
|
mem::release(e->text);
|
||||||
mem::release(e->xV);
|
mem::release(e->xV);
|
||||||
mem::release(e->yV);
|
mem::release(e->yV);
|
||||||
|
_destroy_attr_list(e->attrL);
|
||||||
|
_destroy_css(e->css);
|
||||||
mem::release(e);
|
mem::release(e);
|
||||||
e = e0;
|
e = e0;
|
||||||
}
|
}
|
||||||
@ -105,8 +127,7 @@ namespace cw
|
|||||||
while( r != nullptr )
|
while( r != nullptr )
|
||||||
{
|
{
|
||||||
css_t* r0 = r->link;
|
css_t* r0 = r->link;
|
||||||
mem::release(r->label);
|
_destroy_css(r);
|
||||||
mem::release(r);
|
|
||||||
r = r0;
|
r = r0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +177,7 @@ namespace cw
|
|||||||
|
|
||||||
rc_t _install_gray_scale_cmap( svg_t* p )
|
rc_t _install_gray_scale_cmap( svg_t* p )
|
||||||
{
|
{
|
||||||
unsigned colorN = 255;
|
unsigned colorN = 256;
|
||||||
unsigned* colorV = mem::allocZ<unsigned>(colorN);
|
unsigned* colorV = mem::allocZ<unsigned>(colorN);
|
||||||
|
|
||||||
for(unsigned i=0; i<colorN; ++i)
|
for(unsigned i=0; i<colorN; ++i)
|
||||||
@ -177,7 +198,7 @@ namespace cw
|
|||||||
|
|
||||||
rc_t _install_heat_cmap( svg_t* p )
|
rc_t _install_heat_cmap( svg_t* p )
|
||||||
{
|
{
|
||||||
unsigned colorN = 255;
|
unsigned colorN = 256;
|
||||||
unsigned* colorV = mem::allocZ<unsigned>(colorN);
|
unsigned* colorV = mem::allocZ<unsigned>(colorN);
|
||||||
double rV[] = { 0.0, 0.0, 1.0, 1.0 };
|
double rV[] = { 0.0, 0.0, 1.0, 1.0 };
|
||||||
double gV[] = { 1.0, 0.0, 0.0, 1.0 };
|
double gV[] = { 1.0, 0.0, 0.0, 1.0 };
|
||||||
@ -199,33 +220,7 @@ namespace cw
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
rc_t _install_css(
|
rc_t _insert( svg_t* p, unsigned typeId, double x, double y, double w, double h, const char* text, const double* yV=nullptr, unsigned yN=0, const double* xV=nullptr )
|
||||||
svg_t* p,
|
|
||||||
unsigned cssClassId,
|
|
||||||
const char* cssClassLabel,
|
|
||||||
unsigned strokeColor = 0,
|
|
||||||
unsigned strokeWidth = 1,
|
|
||||||
unsigned fillColor = 0xffffff,
|
|
||||||
unsigned strokeOpacity = 1.0,
|
|
||||||
double fillOpacity = 1.0 )
|
|
||||||
{
|
|
||||||
css_t* r = mem::allocZ<css_t>(1);
|
|
||||||
|
|
||||||
r->id = cssClassId;
|
|
||||||
r->label = mem::duplStr(cssClassLabel==nullptr?" ":cssClassLabel);
|
|
||||||
r->attr.strokeColor = strokeColor;
|
|
||||||
r->attr.strokeWidth = strokeWidth;
|
|
||||||
r->attr.strokeOpacity = strokeOpacity;
|
|
||||||
r->attr.fillColor = fillColor;
|
|
||||||
r->attr.fillOpacity = fillOpacity;
|
|
||||||
|
|
||||||
r->link = p->cssL;
|
|
||||||
p->cssL = r;
|
|
||||||
|
|
||||||
return kOkRC;
|
|
||||||
}
|
|
||||||
|
|
||||||
rc_t _insert( svg_t* p, unsigned typeId, double x, double y, double w, double h, unsigned cssClassId, const char* text, const double* yV=nullptr, unsigned yN=0, const double* xV=nullptr )
|
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
@ -237,7 +232,6 @@ namespace cw
|
|||||||
e->x1 = x+w;
|
e->x1 = x+w;
|
||||||
e->y1 = y+h;
|
e->y1 = y+h;
|
||||||
e->text = mem::duplStr(text);
|
e->text = mem::duplStr(text);
|
||||||
e->cssClassId = cssClassId;
|
|
||||||
e->yV = yN>0 && yV!=nullptr ? mem::allocDupl<double>(yV,yN) : nullptr;
|
e->yV = yN>0 && yV!=nullptr ? mem::allocDupl<double>(yV,yN) : nullptr;
|
||||||
e->xV = yN>0 && xV!=nullptr ? mem::allocDupl<double>(xV,yN) : nullptr;
|
e->xV = yN>0 && xV!=nullptr ? mem::allocDupl<double>(xV,yN) : nullptr;
|
||||||
e->yN = yN;
|
e->yN = yN;
|
||||||
@ -393,76 +387,147 @@ namespace cw
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Write a HTML element attribute list
|
||||||
|
char* _print_ele_attr_list( const attr_t* attrL, char*& s )
|
||||||
|
{
|
||||||
|
for(const attr_t* a=attrL; a!=nullptr; a=a->link)
|
||||||
|
s = mem::printp(s,"%s=\"%s\" ",a->label,a->value);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write a CSS record attribute list
|
||||||
|
char* _print_css_attr_list( const attr_t* attrL, char*& s )
|
||||||
|
{
|
||||||
|
for(const attr_t* a=attrL; a!=nullptr; a=a->link)
|
||||||
|
s = mem::printp(s,"%s: %s;",a->label,a->value);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Print a CSS record
|
||||||
|
char* _print_css( const css_t* r, char*& s )
|
||||||
|
{
|
||||||
|
char* s0 = nullptr;
|
||||||
|
s0 = _print_css_attr_list( r->attrL, s0 );
|
||||||
|
s = mem::printp(s,"%s { %s }\n", r->selectorStr, s0 );
|
||||||
|
mem::release(s0);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* _print_css_list( svg_t* p, char*& s )
|
||||||
|
{
|
||||||
|
for( const css_t* r=p->cssL; r!=nullptr; r=r->link)
|
||||||
|
s = _print_css(r,s);
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
rc_t _writeCssFile( svg_t* p, const char* fn )
|
rc_t _writeCssFile( svg_t* p, const char* fn )
|
||||||
{
|
{
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
file::handle_t fH;
|
file::handle_t fH;
|
||||||
css_t* r;
|
char* s;
|
||||||
|
|
||||||
|
if( p->cssL == nullptr )
|
||||||
|
return kOkRC;
|
||||||
|
|
||||||
if((rc = file::open(fH,fn,file::kWriteFl)) != kOkRC )
|
if((rc = file::open(fH,fn,file::kWriteFl)) != kOkRC )
|
||||||
return cwLogError(rc,"CSS file create failed on '%s'.",cwStringNullGuard(fn));
|
return cwLogError(rc,"CSS file create failed on '%s'.",cwStringNullGuard(fn));
|
||||||
|
|
||||||
for(r=p->cssL; r!=nullptr; r=r->link)
|
s = _print_css_list(p,s);
|
||||||
{
|
|
||||||
file::printf(fH,".%s {\nstroke:#%06x;\nfill:#%06x;\nstroke-width:%i;\nstroke-opacity:%f;\nfill-opacity:%f\n}\n",
|
|
||||||
r->label,r->attr.strokeColor,r->attr.fillColor,r->attr.strokeWidth,r->attr.strokeOpacity,r->attr.fillOpacity);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
file::printf(fH,"%s\n",s);
|
||||||
|
|
||||||
|
mem::release(s);
|
||||||
file::close(fH);
|
file::close(fH);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
css_t* _cssIdToRecd( svg_t* p, unsigned cssClassId )
|
css_t* _cssSelectorToRecd( svg_t* p, const char* selectorStr )
|
||||||
{
|
{
|
||||||
css_t* r = p->cssL;
|
css_t* r = p->cssL;
|
||||||
for(; r!=nullptr; r=r->link)
|
for(; r!=nullptr; r=r->link)
|
||||||
if( r->id == cssClassId )
|
if( strcmp(selectorStr,r->selectorStr)==0 )
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _allocStyleString( svg_t* p, const ele_t* e, bool genInlineFl, char*& s )
|
css_t* _cssCreate( svg_t* p )
|
||||||
{
|
{
|
||||||
s = nullptr;
|
return mem::allocZ<css_t>();
|
||||||
|
}
|
||||||
|
|
||||||
|
css_t* _cssFindOrCreate( svg_t* p, const char* selectorStr )
|
||||||
|
{
|
||||||
css_t* r;
|
css_t* r;
|
||||||
if((r = _cssIdToRecd(p,e->cssClassId)) == nullptr )
|
if((r = _cssSelectorToRecd(p,selectorStr)) == nullptr )
|
||||||
return cwLogError(kGetAttrFailRC,"Unable to locate SVG class id %i.", e->cssClassId );
|
|
||||||
|
|
||||||
if( genInlineFl || e->flags != 0 )
|
|
||||||
{
|
{
|
||||||
attr_t a;
|
r = _cssCreate(p);
|
||||||
|
r->selectorStr = mem::duplStr(selectorStr);
|
||||||
a.strokeColor = cwIsFlag(e->flags,kStrokeColorArgId) ? e->attr.strokeColor : r->attr.strokeColor;
|
r->link = p->cssL;
|
||||||
a.strokeOpacity = cwIsFlag(e->flags,kStrokeOpacityArgId) ? e->attr.strokeOpacity : r->attr.strokeOpacity;
|
p->cssL = r;
|
||||||
a.strokeWidth = cwIsFlag(e->flags,kStrokeWidthArgId) ? e->attr.strokeWidth : r->attr.strokeWidth;
|
|
||||||
a.fillColor = cwIsFlag(e->flags,kFillColorArgId) ? e->attr.fillColor : r->attr.fillColor;
|
|
||||||
a.fillOpacity = cwIsFlag(e->flags,kFillOpacityArgId) ? e->attr.fillOpacity : r->attr.fillOpacity;
|
|
||||||
|
|
||||||
s = mem::printf(s,"style=\"stroke:#%06x;fill:#%06x;stroke-width:%i;stroke-opacity:%f;fill-opacity:%f\"",a.strokeColor,a.fillColor,a.strokeWidth,a.strokeOpacity,a.fillOpacity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* _cssGenUniqueIdLabel( svg_t* p )
|
||||||
|
{
|
||||||
|
unsigned i = 0;
|
||||||
|
const unsigned bufN = 64;
|
||||||
|
char buf[ bufN + 1];
|
||||||
|
do
|
||||||
|
{
|
||||||
|
snprintf(buf,bufN,"#id_%i",i);
|
||||||
|
|
||||||
|
if( _cssSelectorToRecd(p,buf) == nullptr )
|
||||||
|
return mem::duplStr(buf);
|
||||||
|
|
||||||
|
i += 1;
|
||||||
|
}while(1);
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template< typename T >
|
||||||
|
rc_t _set_attr_int( handle_t h, const char* selectorStr, const char* attrLabel, const T& value, const char* suffix )
|
||||||
|
{
|
||||||
|
const int bufN = 64;
|
||||||
|
char buf[ bufN + 1 ];
|
||||||
|
|
||||||
|
if( suffix == nullptr )
|
||||||
|
suffix = "";
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
s = mem::printf(s,"class=\"%s\"",r->label);
|
if( strcmp(suffix,"rgb") == 0 )
|
||||||
|
{
|
||||||
|
snprintf(buf,bufN,"#%06x",value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
snprintf(buf,bufN,"%i%s",value,suffix);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return kOkRC;
|
return _set_attr( h, selectorStr, attrLabel, buf, nullptr );
|
||||||
}
|
}
|
||||||
|
|
||||||
char* _write_pline(char* bodyStr, ele_t* e, const char* styleStr)
|
|
||||||
|
rc_t _write_pline(file::handle_t fH, ele_t* e, const char* styleStr)
|
||||||
{
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
|
|
||||||
if( e->yN == 0 )
|
if( e->yN == 0 )
|
||||||
return bodyStr;
|
return rc;
|
||||||
|
|
||||||
bodyStr = mem::printp(bodyStr,"<polyline points=\"");
|
file::printf(fH,"<polyline points=\"");
|
||||||
for(unsigned i=0; i<e->yN; ++i)
|
for(unsigned i=0; i<e->yN; ++i)
|
||||||
bodyStr = mem::printp(bodyStr,"%f,%f ", e->xV[i], e->yV[i] );
|
if((rc = file::printf(fH,"%f,%f ", e->xV[i], e->yV[i] )) != kOkRC)
|
||||||
|
return rc;
|
||||||
|
|
||||||
return mem::printp(bodyStr,"\" %s />",styleStr);
|
|
||||||
|
return file::printf(fH,"\" %s />\n", styleStr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,22 +537,13 @@ cw::rc_t cw::svg::create( handle_t& h )
|
|||||||
if((rc = destroy(h)) != kOkRC )
|
if((rc = destroy(h)) != kOkRC )
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
svg_t* p = mem::allocZ<svg_t>(1);
|
svg_t* p = mem::allocZ<svg_t>();
|
||||||
|
|
||||||
p->strokeColorIdx = kInvalidIdx;
|
|
||||||
p->strokeWidth = 1;
|
|
||||||
p->fillColorIdx = kInvalidIdx;
|
|
||||||
|
|
||||||
_install_basic_eight_cmap(p);
|
_install_basic_eight_cmap(p);
|
||||||
_install_gray_scale_cmap(p);
|
_install_gray_scale_cmap(p);
|
||||||
_install_inv_gray_scale_cmap(p);
|
_install_inv_gray_scale_cmap(p);
|
||||||
_install_heat_cmap(p);
|
_install_heat_cmap(p);
|
||||||
|
|
||||||
_install_css(p, kRectCssId, "rect" );
|
|
||||||
_install_css(p, kLineCssId, "line" );
|
|
||||||
_install_css(p, kPLineCssId,"pline" );
|
|
||||||
_install_css(p, kTextCssId, "text",0,1,0 );
|
|
||||||
|
|
||||||
h.set(p);
|
h.set(p);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
@ -512,20 +568,6 @@ cw::rc_t cw::svg::destroy( handle_t& h )
|
|||||||
cw::rc_t cw::svg::install_color_map( handle_t h, const unsigned* colorV, unsigned colorN, unsigned id )
|
cw::rc_t cw::svg::install_color_map( handle_t h, const unsigned* colorV, unsigned colorN, unsigned id )
|
||||||
{ return _install_cmap( _handleToPtr(h), id, mem::allocDupl<unsigned>(colorV,colorN), colorN ); }
|
{ return _install_cmap( _handleToPtr(h), id, mem::allocDupl<unsigned>(colorV,colorN), colorN ); }
|
||||||
|
|
||||||
cw::rc_t cw::svg::install_css(
|
|
||||||
handle_t h,
|
|
||||||
unsigned cssClassId,
|
|
||||||
const char* cssClassLabel,
|
|
||||||
unsigned strokeColor,
|
|
||||||
unsigned strokeWidth,
|
|
||||||
unsigned fillColor,
|
|
||||||
unsigned strokeOpacity,
|
|
||||||
double fillOpacity )
|
|
||||||
{
|
|
||||||
svg_t* p = _handleToPtr(h);
|
|
||||||
return _install_css(p, cssClassId, cssClassLabel, strokeColor, strokeWidth, fillColor, strokeOpacity, fillOpacity );
|
|
||||||
}
|
|
||||||
|
|
||||||
void cw::svg::offset( handle_t h, double dx, double dy )
|
void cw::svg::offset( handle_t h, double dx, double dy )
|
||||||
{
|
{
|
||||||
svg_t* p = _handleToPtr(h);
|
svg_t* p = _handleToPtr(h);
|
||||||
@ -544,7 +586,7 @@ unsigned cw::svg::color( handle_t h, unsigned colorMapId, double colorMin, doubl
|
|||||||
}
|
}
|
||||||
|
|
||||||
double c = std::min( colorMax, std::max( colorMin, colorValue ) );
|
double c = std::min( colorMax, std::max( colorMin, colorValue ) );
|
||||||
unsigned idx = cm->colorN * (c - colorMin)/(colorMax - colorMin);
|
unsigned idx = (cm->colorN-1) * (c - colorMin)/(colorMax - colorMin);
|
||||||
|
|
||||||
assert(idx<cm->colorN);
|
assert(idx<cm->colorN);
|
||||||
|
|
||||||
@ -563,78 +605,123 @@ unsigned cw::svg::color( handle_t h, unsigned colorMapId, unsigned colorIdx )
|
|||||||
return cm->colorV[colorIdx];
|
return cm->colorV[colorIdx];
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::svg::_set_attr( handle_t h, argId_t id, const int& value )
|
cw::rc_t cw::svg::_set_attr( handle_t h, const char* selectorStr, const char* attrLabel, const char* value, const char* suffix )
|
||||||
{
|
{
|
||||||
rc_t rc = kOkRC;
|
svg_t* p = _handleToPtr(h);
|
||||||
svg_t* p = _handleToPtr(h);
|
css_t* r = nullptr;
|
||||||
|
int bufN = 64;
|
||||||
|
char buf[ bufN + 1 ];
|
||||||
|
|
||||||
switch( id )
|
|
||||||
|
if( suffix != nullptr )
|
||||||
{
|
{
|
||||||
case kStrokeColorArgId: p->curEle->attr.strokeColor = value; break;
|
snprintf(buf,bufN,"%s%s",value,suffix);
|
||||||
case kStrokeWidthArgId: p->curEle->attr.strokeWidth = value; break;
|
value = buf;
|
||||||
case kFillColorArgId: p->curEle->attr.fillColor = value; break;
|
|
||||||
default:
|
|
||||||
rc = cwLogError(kSetAttrFailRC,"Unknown SVG attribute id: %i", id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if( rc == kOkRC )
|
// allocate and fill the CSS attribute record
|
||||||
p->curEle->flags |= id;
|
attr_t* a = mem::allocZ<attr_t>();
|
||||||
|
a->label = mem::duplStr(attrLabel);
|
||||||
|
a->value = mem::duplStr(value);
|
||||||
|
|
||||||
return rc;
|
// if a selector is given then find or create a CSS selector record
|
||||||
}
|
if( selectorStr != nullptr )
|
||||||
|
r = _cssFindOrCreate(p,selectorStr);
|
||||||
cw::rc_t cw::svg::_set_attr( handle_t h, argId_t id, double value )
|
else
|
||||||
{
|
|
||||||
rc_t rc = kOkRC;
|
|
||||||
svg_t* p = _handleToPtr(h);
|
|
||||||
|
|
||||||
switch( id )
|
|
||||||
{
|
{
|
||||||
case kStrokeOpacityArgId: p->curEle->attr.strokeOpacity = value; break;
|
// 'id' and 'class' attributes are always added to the ele attribute list ...
|
||||||
case kFillOpacityArgId: p->curEle->attr.fillOpacity = value; break;
|
if( strcmp(attrLabel,"id")!=0 && strcmp(attrLabel,"class")!=0 )
|
||||||
default:
|
{
|
||||||
rc = cwLogError(kSetAttrFailRC,"Unknown SVG attribute id: %i", id);
|
// ... otherwise the attributes are added to the ele style list
|
||||||
|
if( p->curEle->css == nullptr )
|
||||||
|
p->curEle->css = _cssCreate(p);
|
||||||
|
r = p->curEle->css;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if( rc == kOkRC )
|
if( r != nullptr )
|
||||||
p->curEle->flags |= id;
|
{
|
||||||
|
a->link = r->attrL;
|
||||||
return rc;
|
r->attrL = a;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
a->link = p->curEle->attrL;
|
||||||
|
p->curEle->attrL = a;
|
||||||
|
}
|
||||||
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::svg::_rect( handle_t h, double x, double y, double ww, double hh, unsigned cssClassId )
|
|
||||||
|
|
||||||
|
cw::rc_t cw::svg::_set_attr( handle_t h, const char* selectorStr, const char* attrLabel, const unsigned& value, const char* suffix )
|
||||||
{
|
{
|
||||||
svg_t* p = _handleToPtr(h);
|
return _set_attr_int(h,selectorStr,attrLabel,value,suffix);
|
||||||
return _insert( p, kRectTId, x, y, ww, hh, cssClassId, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::svg::_line( handle_t h, double x0, double y0, double x1, double y1, unsigned cssClassId )
|
cw::rc_t cw::svg::_set_attr( handle_t h, const char* selectorStr, const char* attrLabel, const int& value, const char* suffix )
|
||||||
{
|
{
|
||||||
svg_t* p = _handleToPtr(h);
|
return _set_attr_int(h,selectorStr,attrLabel,value,suffix);
|
||||||
return _insert( p, kLineTId, x0, y0, x1-x0, y1-y0, cssClassId, nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::svg::_pline( handle_t h, const double* yV, unsigned n, const double* xV, unsigned cssClassId )
|
cw::rc_t cw::svg::_set_attr( handle_t h, const char* selectorStr, const char* attrLabel, const double& value, const char* suffix )
|
||||||
{
|
{
|
||||||
svg_t* p = _handleToPtr(h);
|
const int bufN = 32;
|
||||||
return _insert( p, kPLineTId, 0,0,0,0, cssClassId, nullptr, yV, n, xV);
|
char buf[ bufN+1 ];
|
||||||
|
number_to_string(value,buf,bufN);
|
||||||
|
return _set_attr(h,selectorStr,attrLabel,buf,suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::svg::_text( handle_t h, double x, double y, const char* text, unsigned cssClassId )
|
cw::rc_t cw::svg::_rect( handle_t h, double x, double y, double ww, double hh )
|
||||||
{
|
{
|
||||||
svg_t* p = _handleToPtr(h);
|
svg_t* p = _handleToPtr(h);
|
||||||
return _insert( p, kTextTId, x, y, 0, 0, cssClassId, text);
|
return _insert( p, kRectTId, x, y, ww, hh, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::svg::_line( handle_t h, double x0, double y0, double x1, double y1 )
|
||||||
|
{
|
||||||
|
svg_t* p = _handleToPtr(h);
|
||||||
|
return _insert( p, kLineTId, x0, y0, x1-x0, y1-y0, nullptr);
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::svg::_pline( handle_t h, const double* yV, unsigned n, const double* xV )
|
||||||
|
{
|
||||||
|
svg_t* p = _handleToPtr(h);
|
||||||
|
return _insert( p, kPLineTId, 0,0,0,0, nullptr, yV, n, xV);
|
||||||
|
}
|
||||||
|
|
||||||
|
cw::rc_t cw::svg::_text( handle_t h, double x, double y, const char* text )
|
||||||
|
{
|
||||||
|
svg_t* p = _handleToPtr(h);
|
||||||
|
return _insert( p, kTextTId, x, y, 0, 0, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::svg::image( handle_t h, const float* xM, unsigned rowN, unsigned colN, unsigned pixSize, unsigned cmapId )
|
cw::rc_t cw::svg::image( handle_t h, const float* xM, unsigned rowN, unsigned colN, unsigned pixSize, unsigned cmapId )
|
||||||
{
|
{
|
||||||
|
svg_t* p = _handleToPtr(h);
|
||||||
|
char* idLabel = _cssGenUniqueIdLabel(p);
|
||||||
|
|
||||||
|
_parse_attr( h, idLabel,
|
||||||
|
"width", pixSize, "px",
|
||||||
|
"height", pixSize, "px",
|
||||||
|
"stroke-width", 1, "px",
|
||||||
|
"stroke-opacity", 1.0, nullptr,
|
||||||
|
"fill-opacity", 1.0, nullptr );
|
||||||
|
|
||||||
for(unsigned i=0; i<rowN; ++i)
|
for(unsigned i=0; i<rowN; ++i)
|
||||||
for(unsigned j=0; j<colN; ++j)
|
for(unsigned j=0; j<colN; ++j)
|
||||||
{
|
{
|
||||||
int c = color( h, cmapId, 0, 1, xM[j*colN + i + 1] );
|
int c = color( h, cmapId, 0, 1, xM[j*colN + i + 1] );
|
||||||
rect(h, i*pixSize, j*pixSize, pixSize, pixSize, kRectCssId, kFillColorArgId, c, kStrokeColorArgId, c );
|
|
||||||
|
_insert(p, kPixelTId, i*pixSize, j*pixSize, pixSize, pixSize, nullptr );
|
||||||
|
_set_attr( h, nullptr, "stroke", c, "rgb" );
|
||||||
|
_set_attr( h, nullptr, "fill", c, "rgb" );
|
||||||
|
_set_attr( h, nullptr, "id", idLabel+1, nullptr );
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mem::release(idLabel);
|
||||||
|
|
||||||
return kOkRC;
|
return kOkRC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -645,13 +732,13 @@ cw::rc_t cw::svg::write( handle_t h, const char* outFn, const char* cssFn, unsig
|
|||||||
double svgWidth = 0;
|
double svgWidth = 0;
|
||||||
double svgHeight = 0;
|
double svgHeight = 0;
|
||||||
char* cssStr = nullptr;
|
char* cssStr = nullptr;
|
||||||
|
char* styleStr = nullptr;
|
||||||
char* fileHdr = nullptr;
|
char* fileHdr = nullptr;
|
||||||
char* svgHdr = nullptr;
|
char* svgHdr = nullptr;
|
||||||
char* bodyStr = nullptr;
|
|
||||||
ele_t* e = p->eleL;
|
ele_t* e = p->eleL;
|
||||||
bool standAloneFl = cwIsFlag(flags,kStandAloneFl);
|
bool standAloneFl = cwIsFlag(flags,kStandAloneFl);
|
||||||
bool panZoomFl = cwIsFlag(flags,kPanZoomFl);
|
bool panZoomFl = cwIsFlag(flags,kPanZoomFl);
|
||||||
bool genInlineStyleFl = cwIsFlag(flags,kGenInlineStyleFl);
|
//bool genInlineStyleFl = cwIsFlag(flags,kGenInlineStyleFl);
|
||||||
bool genCssFileFl = cwIsFlag(flags,kGenCssFileFl) && cssFn!=nullptr;
|
bool genCssFileFl = cwIsFlag(flags,kGenCssFileFl) && cssFn!=nullptr;
|
||||||
//bool drawFrameFl = cwIsFlag(flags,kDrawFrameFl);
|
//bool drawFrameFl = cwIsFlag(flags,kDrawFrameFl);
|
||||||
|
|
||||||
@ -671,6 +758,7 @@ cw::rc_t cw::svg::write( handle_t h, const char* outFn, const char* cssFn, unsig
|
|||||||
"<head>\n"
|
"<head>\n"
|
||||||
"<meta charset=\"utf-8\">\n"
|
"<meta charset=\"utf-8\">\n"
|
||||||
"%s"
|
"%s"
|
||||||
|
"<style>%s</style>\n"
|
||||||
"%s\n"
|
"%s\n"
|
||||||
"</head>\n"
|
"</head>\n"
|
||||||
"<body onload=\"doOnLoad()\">\n";
|
"<body onload=\"doOnLoad()\">\n";
|
||||||
@ -678,21 +766,27 @@ cw::rc_t cw::svg::write( handle_t h, const char* outFn, const char* cssFn, unsig
|
|||||||
char svgFmt[] = "<svg id=\"mysvg\" width=\"%f\" height=\"%f\">\n";
|
char svgFmt[] = "<svg id=\"mysvg\" width=\"%f\" height=\"%f\">\n";
|
||||||
char cssFmt[] = "<link rel=\"stylesheet\" type=\"text/css\" href=\"%s\">\n";
|
char cssFmt[] = "<link rel=\"stylesheet\" type=\"text/css\" href=\"%s\">\n";
|
||||||
|
|
||||||
double max_y = _size(p, svgWidth, svgHeight );
|
//double max_y = _size(p, svgWidth, svgHeight );
|
||||||
|
//_flipY( p, max_y );
|
||||||
_flipY( p, max_y );
|
_size(p,svgWidth,svgHeight);
|
||||||
|
|
||||||
_offsetEles(p, bordR, bordT );
|
_offsetEles(p, bordR, bordT );
|
||||||
|
|
||||||
svgWidth += bordR + bordL;
|
svgWidth += bordR + bordL;
|
||||||
svgHeight += bordT + bordB;
|
svgHeight += bordT + bordB;
|
||||||
|
|
||||||
if( genCssFileFl )
|
|
||||||
_writeCssFile( p, cssFn );
|
if( p->cssL != nullptr )
|
||||||
|
{
|
||||||
|
if( genCssFileFl )
|
||||||
|
_writeCssFile( p, cssFn );
|
||||||
|
else
|
||||||
|
styleStr = _print_css_list(p,styleStr);
|
||||||
|
}
|
||||||
|
|
||||||
cssStr = mem::printf(cssStr,cssFn==nullptr ? "%s" : cssFmt, cssFn==nullptr ? " " : cssFn);
|
cssStr = mem::printf(cssStr,cssFn==nullptr ? "%s" : cssFmt, cssFn==nullptr ? " " : cssFn);
|
||||||
|
|
||||||
fileHdr = mem::printf(fileHdr, standAloneFmt, cssStr, panZoomFl ? panZoomHdr : "");
|
fileHdr = mem::printf(fileHdr,standAloneFmt, cssStr, styleStr==nullptr ? "" : styleStr, panZoomFl ? panZoomHdr : "");
|
||||||
|
|
||||||
svgHdr = mem::printf(svgHdr,"%s%s", standAloneFl ? fileHdr : "", svgFmt);
|
svgHdr = mem::printf(svgHdr,"%s%s", standAloneFl ? fileHdr : "", svgFmt);
|
||||||
|
|
||||||
@ -700,44 +794,8 @@ cw::rc_t cw::svg::write( handle_t h, const char* outFn, const char* cssFn, unsig
|
|||||||
|
|
||||||
mem::release(svgHdr);
|
mem::release(svgHdr);
|
||||||
mem::release(cssStr);
|
mem::release(cssStr);
|
||||||
|
mem::release(styleStr);
|
||||||
|
|
||||||
for(; e!=NULL; e=e->link)
|
|
||||||
{
|
|
||||||
char* styleStr = nullptr;
|
|
||||||
|
|
||||||
if((rc = _allocStyleString( p, e, genInlineStyleFl, styleStr )) != kOkRC )
|
|
||||||
goto errLabel;
|
|
||||||
|
|
||||||
switch( e->typeId )
|
|
||||||
{
|
|
||||||
case kRectTId:
|
|
||||||
bodyStr = mem::printp(bodyStr,"<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" %s/>\n",e->x0,e->y0,e->x1-e->x0,e->y1-e->y0,styleStr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case kLineTId:
|
|
||||||
bodyStr = mem::printp(bodyStr,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" %s/>\n",e->x0,e->y0,e->x1,e->y1,styleStr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case kPLineTId:
|
|
||||||
bodyStr = _write_pline(bodyStr,e,styleStr);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case kTextTId:
|
|
||||||
bodyStr = mem::printp(bodyStr,"<text x=\"%f\" y=\"%f\" %s>%s</text>\n",e->x0,e->y0, styleStr,e->text);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
mem::release(styleStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if( (bodyStr = textAppend(bodyStr,"</svg>\n")) == NULL )
|
|
||||||
{
|
|
||||||
rc = cwLogError(kMemAllocFailRC,"File suffix write failed.");
|
|
||||||
goto errLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( standAloneFl )
|
|
||||||
bodyStr = textAppend(bodyStr,"</body>\n</html>\n");
|
|
||||||
|
|
||||||
if((rc = file::open(fH,outFn,file::kWriteFl)) != kOkRC )
|
if((rc = file::open(fH,outFn,file::kWriteFl)) != kOkRC )
|
||||||
{
|
{
|
||||||
@ -745,43 +803,104 @@ cw::rc_t cw::svg::write( handle_t h, const char* outFn, const char* cssFn, unsig
|
|||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileHdr = textAppend(fileHdr,bodyStr);
|
if((rc = file::printf(fH,"%s",fileHdr)) != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
|
||||||
if((rc = file::printf(fH,fileHdr)) != kOkRC )
|
for(; e!=NULL; e=e->link)
|
||||||
{
|
{
|
||||||
rc = cwLogError(rc,"SVG file write failed on '%s'.",outFn);
|
char* dStyleStr = nullptr;
|
||||||
|
|
||||||
|
if( e->css != nullptr )
|
||||||
|
dStyleStr = mem::printf(dStyleStr, "style=\"%s\" ",_print_css_attr_list(e->css->attrL,dStyleStr));
|
||||||
|
|
||||||
|
if( e->attrL != nullptr )
|
||||||
|
dStyleStr = mem::printp(dStyleStr,"%s",_print_ele_attr_list(e->attrL,dStyleStr) );
|
||||||
|
|
||||||
|
const char* styleStr = dStyleStr==nullptr ? "" : dStyleStr;
|
||||||
|
|
||||||
|
switch( e->typeId )
|
||||||
|
{
|
||||||
|
case kRectTId:
|
||||||
|
rc = file::printf(fH,"<rect x=\"%f\" y=\"%f\" width=\"%f\" height=\"%f\" %s/>\n",e->x0,e->y0,e->x1-e->x0,e->y1-e->y0,styleStr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kPixelTId:
|
||||||
|
rc = file::printf(fH,"<rect x=\"%f\" y=\"%f\" %s/>\n",e->x0,e->y0,e->x1-e->x0,e->y1-e->y0,styleStr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kLineTId:
|
||||||
|
rc = file::printf(fH,"<line x1=\"%f\" y1=\"%f\" x2=\"%f\" y2=\"%f\" %s/>\n",e->x0,e->y0,e->x1,e->y1,styleStr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kPLineTId:
|
||||||
|
rc = _write_pline(fH,e,styleStr);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case kTextTId:
|
||||||
|
rc = file::printf(fH,"<text x=\"%f\" y=\"%f\" %s>%s</text>\n",e->x0,e->y0, styleStr,e->text);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mem::release(dStyleStr);
|
||||||
|
|
||||||
|
if( rc != kOkRC )
|
||||||
|
goto errLabel;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( (rc = file::printf(fH,"</svg>\n")) != kOkRC )
|
||||||
|
{
|
||||||
|
rc = cwLogError(kMemAllocFailRC,"File suffix write failed.");
|
||||||
goto errLabel;
|
goto errLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( standAloneFl )
|
||||||
|
rc = file::printf(fH,"</body>\n</html>\n");
|
||||||
|
|
||||||
|
|
||||||
errLabel:
|
errLabel:
|
||||||
file::close(fH);
|
|
||||||
|
if( rc != kOkRC )
|
||||||
|
rc = cwLogError(rc,"SVG file write failed.");
|
||||||
|
file::close(fH);
|
||||||
|
|
||||||
mem::release(fileHdr);
|
mem::release(fileHdr);
|
||||||
mem::release(bodyStr);
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
cw::rc_t cw::svg::test( const char* outFn, const char* cssFn )
|
cw::rc_t cw::svg::test( const char* outFn, const char* cssFn )
|
||||||
{
|
{
|
||||||
|
rc_t rc = kOkRC;
|
||||||
rc_t rc = kOkRC;
|
|
||||||
|
|
||||||
handle_t h;
|
handle_t h;
|
||||||
|
|
||||||
if((rc = create(h)) != kOkRC )
|
if((rc = create(h)) != kOkRC )
|
||||||
cwLogError(rc,"SVG Test failed on create.");
|
cwLogError(rc,"SVG Test failed on create.");
|
||||||
|
|
||||||
|
|
||||||
double yV[] = { 0, 10, 30, 60, 90 };
|
double yV[] = { 0, 10, 30, 60, 90 };
|
||||||
|
double xV[] = { 0, 40, 60, 40, 10 };
|
||||||
unsigned yN = cwCountOf(yV);
|
unsigned yN = cwCountOf(yV);
|
||||||
|
|
||||||
rect(h, 0, 0, 100, 100, kRectCssId, kFillColorArgId, 0x7f7f7f );
|
install_css(h,"#my_rect","fill-opacity",0.25,nullptr);
|
||||||
line(h, 0, 0, 100, 100, kLineCssId, kStrokeColorArgId, 0xff0000 );
|
|
||||||
line(h, 0,100, 100, 0, kLineCssId, kStrokeColorArgId, 0x00ff00, kStrokeWidthArgId, 3, kStrokeOpacityArgId, 0.5 );
|
rect(h, 0, 0, 100, 100, "fill", 0x7f7f7f, "rgb", "id", "my_rect", nullptr );
|
||||||
pline(h, yV, yN );
|
line(h, 0, 0, 100, 100, "stroke", 0xff0000, "rgb" );
|
||||||
text(h, 10, 10, "foo");
|
line(h, 0,100, 100, 0, "stroke", 0x00ff00, "rgb", "stroke-width", 3, "px", "stroke-opacity", 0.5, nullptr );
|
||||||
|
pline(h, yV, yN, xV, "stroke", 0x0, "rgb", "fill-opacity", 0.25, nullptr );
|
||||||
|
text(h, 10, 10, "foo" );
|
||||||
|
|
||||||
|
float imgM[] = {
|
||||||
|
0.0f, 0.5f, 1.0f,
|
||||||
|
0.5f, 0.0f, 0.5f,
|
||||||
|
1.0f, 1.0f, 0.0f,
|
||||||
|
0.5f, 0.0f, 1.0f };
|
||||||
|
|
||||||
|
offset( h, 10, 200 );
|
||||||
|
image(h, imgM, 4, 3, 20, kInvGrayScaleColorMapId );
|
||||||
|
|
||||||
|
|
||||||
|
write(h,outFn, cssFn, kStandAloneFl, 10,10,10,10);
|
||||||
|
|
||||||
write(h,outFn, cssFn, kStandAloneFl | kGenCssFileFl, 10,10,10,10);
|
|
||||||
if((rc = destroy(h)) != kOkRC )
|
if((rc = destroy(h)) != kOkRC )
|
||||||
cwLogError(rc,"SVG destroy failed.");
|
cwLogError(rc,"SVG destroy failed.");
|
||||||
|
|
||||||
|
90
cwSvg.h
90
cwSvg.h
@ -16,97 +16,81 @@ namespace cw
|
|||||||
kBaseUserColorMapId
|
kBaseUserColorMapId
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum
|
|
||||||
{
|
|
||||||
kStrokeColorArgId = 0x01,
|
|
||||||
kStrokeWidthArgId = 0x02,
|
|
||||||
kStrokeOpacityArgId = 0x04,
|
|
||||||
kFillColorArgId = 0x08,
|
|
||||||
kFillOpacityArgId = 0x10
|
|
||||||
} argId_t;
|
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
kRectCssId,
|
|
||||||
kLineCssId,
|
|
||||||
kPLineCssId,
|
|
||||||
kTextCssId,
|
|
||||||
kBaseCssId
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
rc_t create( handle_t& h );
|
rc_t create( handle_t& h );
|
||||||
rc_t destroy( handle_t& h );
|
rc_t destroy( handle_t& h );
|
||||||
|
|
||||||
rc_t install_color_map( handle_t h, const unsigned* colorV, unsigned colorN, unsigned colorId=kBaseUserColorMapId );
|
rc_t install_color_map( handle_t h, const unsigned* colorV, unsigned colorN, unsigned colorId=kBaseUserColorMapId );
|
||||||
|
|
||||||
rc_t install_css(
|
|
||||||
handle_t h,
|
|
||||||
unsigned cssClassId,
|
|
||||||
const char* cssClass = nullptr,
|
|
||||||
unsigned strokeColor = 0,
|
|
||||||
unsigned strokeWidth = 1,
|
|
||||||
unsigned fillColor = 0xffffff,
|
|
||||||
unsigned strokeOpacity = 1.0,
|
|
||||||
double fillOpacity = 1.0 );
|
|
||||||
|
|
||||||
void offset( handle_t h, double dx, double dy );
|
void offset( handle_t h, double dx, double dy );
|
||||||
unsigned color( handle_t h, unsigned colorMapId, double colorMin, double colorMax, double colorValue );
|
unsigned color( handle_t h, unsigned colorMapId, double colorMin, double colorMax, double colorValue );
|
||||||
unsigned color( handle_t h, unsigned colorMapId, unsigned colorIdx );
|
unsigned color( handle_t h, unsigned colorMapId, unsigned colorIdx );
|
||||||
|
|
||||||
rc_t _set_attr( handle_t h, argId_t id, const int& value );
|
rc_t _set_attr( handle_t h, const char* selectorStr, const char* attrLabel, const char* value, const char* suffix );
|
||||||
rc_t _set_attr( handle_t h, argId_t id, double value );
|
rc_t _set_attr( handle_t h, const char* selectorStr, const char* attrLabel, const unsigned& value, const char* suffix );
|
||||||
|
rc_t _set_attr( handle_t h, const char* selectorStr, const char* attrLabel, const int& value, const char* suffix );
|
||||||
|
rc_t _set_attr( handle_t h, const char* selectorStr, const char* attrLabel, const double& value, const char* suffix );
|
||||||
|
|
||||||
inline rc_t _parse_attr( handle_t h ){ return kOkRC; }
|
inline rc_t _parse_attr( handle_t h, const char* selectorStr ){ return kOkRC; }
|
||||||
|
|
||||||
template<typename T0, typename T1, typename ...ARGS>
|
template<typename T, typename ...ARGS>
|
||||||
rc_t _parse_attr( handle_t h, T0 id, T1 val, ARGS&&... args )
|
rc_t _parse_attr( handle_t h, const char* selectorStr, const char* attrLabel, const T& val, const char* suffix, ARGS&&... args )
|
||||||
{
|
{
|
||||||
rc_t rc;
|
rc_t rc;
|
||||||
if((rc = _set_attr(h, id,val)) == kOkRC )
|
if((rc = _set_attr(h, selectorStr, attrLabel, val, suffix)) == kOkRC )
|
||||||
rc =_parse_attr( h, std::forward<ARGS>(args)...);
|
rc =_parse_attr( h, selectorStr, std::forward<ARGS>(args)...);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _rect( handle_t h, double x, double y, double ww, double hh, unsigned cssClassId );
|
// Install a CSS selector record.
|
||||||
|
// Style attributes are encoded as triples "<label>" <value> "<suffix>".
|
||||||
|
// Color values are encoded with the <suffix> = "rgb"
|
||||||
|
template< typename ...ARGS>
|
||||||
|
rc_t install_css( handle_t h, const char* selectorStr, ARGS&&... args )
|
||||||
|
{ return _parse_attr( h, selectorStr, std::forward<ARGS>(args)...); }
|
||||||
|
|
||||||
|
rc_t _rect( handle_t h, double x, double y, double ww, double hh );
|
||||||
|
|
||||||
// Draw a rectangle. The variable arg. list must be <argId>,<value> pairs.
|
// Draw a rectangle. The variable arg. list must be <argId>,<value> pairs.
|
||||||
|
// All attributes assigned here will be encoded inside the SVG element tag.
|
||||||
|
// Attributes are encoded as triples "<label>" <value> "<suffix>".
|
||||||
|
// Color values are encoded with the <suffix> = "rgb"
|
||||||
template<typename ...ARGS>
|
template<typename ...ARGS>
|
||||||
rc_t rect( handle_t h, double x, double y, double ww, double hh, unsigned cssClassId, ARGS&&... args )
|
rc_t rect( handle_t h, double x, double y, double ww, double hh, ARGS&&... args )
|
||||||
{
|
{
|
||||||
_rect( h, x, y, ww, hh, cssClassId );
|
_rect( h, x, y, ww, hh );
|
||||||
return _parse_attr( h, std::forward<ARGS>(args)...);
|
return _parse_attr( h, nullptr, std::forward<ARGS>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _line( handle_t h, double x0, double y0, double x1, double y1, unsigned cssClassId );
|
rc_t _line( handle_t h, double x0, double y0, double x1, double y1 );
|
||||||
|
|
||||||
|
|
||||||
// Draw a line. The variable arg. list must be <argId>,<value> pairs.
|
// Draw a line. The variable arg. list must be <argId>,<value> pairs.
|
||||||
template<typename ...ARGS>
|
template<typename ...ARGS>
|
||||||
rc_t line( handle_t h, double x0, double y0, double x1, double y1, unsigned cssClassId=kLineCssId, ARGS&&... args )
|
rc_t line( handle_t h, double x0, double y0, double x1, double y1, ARGS&&... args )
|
||||||
{
|
{
|
||||||
_line( h, x0, y0, x1, y1, cssClassId );
|
_line( h, x0, y0, x1, y1 );
|
||||||
return _parse_attr( h, std::forward<ARGS>(args)...);
|
return _parse_attr( h, nullptr, std::forward<ARGS>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _pline( handle_t h, const double* yV, unsigned n, const double* xV, unsigned cssClassId );
|
rc_t _pline( handle_t h, const double* yV, unsigned n, const double* xV );
|
||||||
|
|
||||||
// Draw a poly-line. The variable arg. list must be <argId>,<value> pairs.
|
// Draw a poly-line. The variable arg. list must be <argId>,<value> pairs. Set xV to nullptr to use index as x.
|
||||||
template<typename ...ARGS>
|
template<typename ...ARGS>
|
||||||
rc_t pline( handle_t h, const double* yV, unsigned n, const double* xV=nullptr, unsigned cssClassId=kPLineCssId, ARGS&&... args )
|
rc_t pline( handle_t h, const double* yV, unsigned n, const double* xV, ARGS&&... args )
|
||||||
{
|
{
|
||||||
_pline( h, yV, n, xV, cssClassId );
|
_pline( h, yV, n, xV );
|
||||||
return _parse_attr( h, std::forward<ARGS>(args)...);
|
return _parse_attr( h, nullptr, std::forward<ARGS>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc_t _text( handle_t h, double x, double y, const char* text, unsigned cssClassId );
|
rc_t _text( handle_t h, double x, double y, const char* text );
|
||||||
|
|
||||||
// Draw text. The variable arg. list must be <argId>,<value> pairs.
|
// Draw text. The variable arg. list must be <argId>,<value> pairs.
|
||||||
template<typename ...ARGS>
|
template<typename ...ARGS>
|
||||||
rc_t text( handle_t h, double x, double y, const char* text, unsigned cssClassId=kTextCssId, ARGS&&... args )
|
rc_t text( handle_t h, double x, double y, const char* text, ARGS&&... args )
|
||||||
{
|
{
|
||||||
_text( h, x, y, text, cssClassId );
|
_text( h, x, y, text );
|
||||||
return _parse_attr( h, std::forward<ARGS>(args)...);
|
return _parse_attr( h, nullptr, std::forward<ARGS>(args)...);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user