📄 export.cpp
字号:
{
wmfRect rc = {7, 0x41B, iy2, ix2, iy1, ix1};
write(oFile, &rc, 14);
}
void
ExportWMF::wmfSelectObject(unsigned short o)
{
wmfObjShort so = {4, 0x12D, o};
write(oFile, &so, 8);
}
void
ExportWMF::wmfSetBkColor(DWORD col)
{
wmfObjCol co = {5, 0x201};
write(oFile, &co, 6);
write(oFile, &col, 4);
}
void
ExportWMF::wmfSetBkMode(unsigned m)
{
wmfObjShort mo = {5, 0x102, m & 0xffff};
unsigned short p;
write(oFile, &mo, 8);
p = m>>16;
write(oFile, &p, 2);
}
//cmSetMapMode()
//cmSetPolyFillMode()
void
ExportWMF::wmfSetTextAlign(unsigned a)
{
wmfObjShort ao = {5, 0x12E, a & 0xffff};
unsigned short p;
write(oFile, &ao, 8);
p = a>>16;
write(oFile, &p, 2);
}
void
ExportWMF::wmfSetTextColor(DWORD col)
{
wmfObjCol tc = {5, 0x209};
write(oFile, &tc, 6);
write(oFile, &col, 4);
}
//cmSetWindowExt()
//cmSetWindowOrg()
void
ExportWMF::wmfTextOut(unsigned short ix1, unsigned short iy1, char *txt, unsigned short cb)
{
wmfObjShort to = {6, 0x521, cb};
unsigned short le, v[2] = {iy1, ix1};
le = cb &1 ? cb+1 : cb;
to.Size += le>>1;
write(oFile, &to, 8);
write(oFile, txt, le);
write(oFile, &v, 4);
if(to.Size > rec_size) rec_size = to.Size;
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Entry point to export graph to Windows Meta File
void DoExportWmf(GraphObj *g, char *FileName, float res, DWORD flags)
{
ExportWMF *ex;
ex = new ExportWMF(g, FileName, res, flags);
if(ex->StartPage()) {
g->DoPlot(ex);
ex->EndPage();
}
delete(ex);
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// export to *.svg file (scalable vector graphic)
// this code is based on information from the following books
// H. Spona, 'Das Einsteigerseminar SVG-Webgrafiken mit XML',
// vmi, ISBN 3-8266-7181-3
// M. Salathe, 'SVG Scalabe Vector Graphics ...f黵 professionelle Einsteiger',
// M&T, ISBN 3-8272-6188-0
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class ExportSVG:public anyOutput {
public:
HatchOut *hgo;
ExportSVG(GraphObj *g, char *FileName, DWORD flags);
~ExportSVG();
bool SetLine(LineDEF *lDef);
bool SetFill(FillDEF *fill);
bool SetTextSpec(TextDEF *set);
bool StartPage();
bool EndPage();
bool oCircle(int x1, int y1, int x2, int y2, char* nam = 0L);
bool oPolyline(POINT * pts, int cp, char *nam = 0L);
bool oRectangle(int x1, int y1, int x2, int y2, char *nam = 0L);
bool oSolidLine(POINT *p);
bool oTextOut(int x, int y, char *txt, int cb);
bool oPolygon(POINT *pts, int cp, char * nam = 0L);
private:
int iLineWidth;
bool bUseGroupLine, bOutputPending;
GraphObj *go;
char *name, indent[80], output[120], tHatchStyle[80];
FILE *oFile;
DWORD flags;
void Indent(bool ind);
void AddToOutput(char *txt);
char *ColName(DWORD col);
};
ExportSVG::ExportSVG(GraphObj *g, char *FileName, DWORD flg)
{
hgo =0L;
DeskRect.left = DeskRect.top = 0;
DeskRect.right = DeskRect.bottom = 0x4fffffff;
dFillCol = 0xffffffffL;
hres = vres = 1000.0f;
go = g;
if(FileName)name = strdup(FileName);
else name = 0L;
oFile = 0L;
flags = flg;
strcpy(indent, " ");
strcpy(tHatchStyle, "style=\"stroke:black; stroke-width:1\"");
bUseGroupLine = false;
}
ExportSVG::~ExportSVG()
{
if(hgo) delete hgo;
if(name) free(name);
}
bool
ExportSVG::SetLine(LineDEF *lDef)
{
LineWidth = lDef->width;
if(1 >(iLineWidth = iround(un2fix(lDef->width)))) iLineWidth = 1;
dPattern = lDef->pattern;
dLineCol = lDef->color;
RLP.finc = (float)(256.0/un2fix(lDef->patlength*8.0));
RLP.fp = 0.0;
return true;
}
bool
ExportSVG::SetFill(FillDEF *fill)
{
int iL;
if(!fill) return false;
if((fill->type & 0xff) != FILL_NONE) {
if(!hgo) hgo = new HatchOut(this);
if(hgo) hgo->SetFill(fill);
if(fill->hatch) {
if(1 >(iL = iround(un2fix(fill->hatch->width)))) iL = 1;
sprintf(tHatchStyle, "style=\"fill:none; stroke:%s; stroke-width:%d\"",
ColName(fill->hatch->color), iL);
}
}
else {
if(hgo) delete hgo;
hgo = 0L;
}
dFillCol = fill->color;
dFillCol2 = fill->color2;
return true;
}
bool
ExportSVG::SetTextSpec(TextDEF *set)
{
if(!set->iSize && set->fSize > 0.0f) set->iSize = un2iy(set->fSize);
if(!set->iSize) return false;
return anyOutput::SetTextSpec(set);
}
bool
ExportSVG::StartPage()
{
int w, h;
if(!go) return false;
w = un2ix(go->GetSize(SIZE_GRECT_RIGHT) - go->GetSize(SIZE_GRECT_LEFT))/10;
h = un2iy(go->GetSize(SIZE_GRECT_BOTTOM) - go->GetSize(SIZE_GRECT_TOP))/10;
w++; h++;
if(name) {
oFile = fopen(name, "w");
if(!oFile) {
ErrorBox("Could not open\noutput file!");
return false;
}
}
else oFile = stdout;
if(flags & 0x01) fprintf(oFile, "Content-Type: image/svg+xml\n\n");
VPorg.fy = -un2fiy(go->GetSize(SIZE_GRECT_TOP));
VPorg.fx = -un2fix(go->GetSize(SIZE_GRECT_LEFT));
fprintf(oFile, "<?xml version=\"1.0\"?>\n"
"<!DOCTYPE svg PUBLIC \"-//W3C//DTD SVG 20001102//EN\"\n"
" \"http://www.w3.org/TR/2000/CR-SVG-20001102/DTD/svg-20001102.dtd\">\n");
fprintf(oFile, "<svg %s width=\"%d\" height=\"%d\" style=\"stroke-linecap:round\">\n",
defs.svgAttr ? defs.svgAttr : "", w, h);
if(defs.svgScript) {
fprintf(oFile, "<defs>\n<script type=\"text/ecmascript\"><![CDATA[\n");
fprintf(oFile, "\n%s\n", defs.svgScript);
fprintf(oFile, "\n]]></script>\n</defs>\n\n");
}
fprintf(oFile, "<g transform=\"scale(0.1)\" style=\"font-family:Helvetica\">\n");
return true;
}
bool
ExportSVG::EndPage()
{
fprintf(oFile, "</g>\n</svg>\n");
fclose (oFile);
return true;
}
bool
ExportSVG::oCircle(int x1, int y1, int x2, int y2, char* nam)
{
if(x1 > x2) Swap(x1, x2);
if(y1 > y2) Swap(y1, y2);
if(hgo){
fprintf(oFile, "%s<g> <!-- %s with pattern -->\n", indent,
(x2-x1) == (y2-y1) ? "circle" : "ellipse");
Indent(true);
}
fprintf(oFile, "%s<%s%s%s%s cx=\"%d\" cy=\"%d\" ", indent,
(x2-x1) == (y2-y1) ? "circle" : "ellipse", nam? " name=\"" : "",
nam ? nam : "", nam ? "\"" : "", (x1+x2)/2, (y1+y2)/2);
if((x2-x1) == (y2-y1)) fprintf(oFile, "r=\"%d\"", (x2-x1)/2);
else fprintf(oFile, "rx=\"%d\" ry=\"%d\"", (x2-x1)/2, (y2-y1)/2);
fprintf(oFile, " style=\"fill:%s; stroke:%s; stroke-width:%d\"/>\n",
ColName(dFillCol), ColName(dLineCol), iLineWidth);
if(hgo) {
fprintf(oFile, "%s<g %s> <!-- hatch -->\n", indent, tHatchStyle);
Indent(true);
bUseGroupLine = true;
hgo->oCircle(x1, y1, x2, y2);
Indent(false);
bUseGroupLine = false;
fprintf(oFile, "%s</g>\n", indent);
Indent(false);
fprintf(oFile, "%s</g>\n", indent);
}
return true;
}
bool
ExportSVG::oPolyline(POINT *pts, int cp, char *nam)
{
int i;
char tmptxt[40];
if(cp < 2) return false;
if (dPattern){
fprintf(oFile, "%s<g style=\"stroke:%s; stroke-width:%d; stroke-linecap:round\">"
"<!-- pattern line -->\n", indent, ColName(dLineCol), iLineWidth);
Indent(true);
bUseGroupLine = true;
for (i = 1; i < cp; i++) PatLine(pts[i-1], pts[i]);
Indent(false);
fprintf(oFile, "%s</g>\n", indent);
bUseGroupLine = false;
}
else {
if(cp == 2) return oSolidLine(pts);
bOutputPending = false;
sprintf(output, "<polyline points=\"");
for(i = 0; i < cp; i++) {
sprintf(tmptxt, "%d %d ", pts[i].x, pts[i].y);
AddToOutput(tmptxt);
}
i = strlen(output);
if(i) output[i-1] = 0;
strcat(output, "\"");
if(!bUseGroupLine) {
strcpy(tmptxt, " style = \"fill:none; ");
AddToOutput(tmptxt);
sprintf(tmptxt, "; stroke:%s; ", ColName(dLineCol));
AddToOutput(tmptxt);
sprintf(tmptxt, "stroke-width:%d\"/>",iLineWidth);
AddToOutput(tmptxt);
}
else strcat(output, "/>");
fprintf(oFile, "%s%s\n", indent, output);
if(bOutputPending)Indent(false);
}
return true;
}
bool
ExportSVG::oRectangle(int x1, int y1, int x2, int y2, char *nam)
{
if(x1 > x2) Swap(x1, x2);
if(y1 > y2) Swap(y1, y2);
if(hgo){
fprintf(oFile, "%s<g> <!-- rectangle with pattern -->\n", indent);
Indent(true);
}
fprintf(oFile, "%s<rect%s%s%s x=\"%d\" y=\"%d\" width=\"%d\" height=\"%d\" "
"style=\"fill:%s; stroke:%s; stroke-width:%d\"/>\n",
indent, nam? " name=\"" : "", nam ? nam : "", nam ? "\"" : "",
x1, y1, x2-x1-1, y2-y1-1, ColName(dFillCol), ColName(dLineCol), iLineWidth);
if(hgo) {
fprintf(oFile, "%s<g %s> <!-- hatch -->\n", indent, tHatchStyle);
Indent(true);
bUseGroupLine = true;
hgo->oRectangle(x1, y1, x2, y2, 0L);
Indent(false);
bUseGroupLine = false;
fprintf(oFile, "%s</g>\n", indent);
Indent(false);
fprintf(oFile, "%s</g>\n", indent);
}
return true;
}
bool
ExportSVG::oSolidLine(POINT *p)
{
if(bUseGroupLine) fprintf(oFile, "%s<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\"/>\n",
indent, p[0].x, p[0].y, p[1].x, p[1].y);
else fprintf(oFile, "%s<line x1=\"%d\" y1=\"%d\" x2=\"%d\" y2=\"%d\" "
"style=\"stroke:%s; stroke-width:%d\"/>\n",
indent, p[0].x, p[0].y, p[1].x, p[1].y, ColName(dLineCol), iLineWidth);
return true;
}
bool
ExportSVG::oTextOut(int x, int y, char *txt, int cb)
{
int i, h, ix, iy;
char tmptxt[140], *nt;
if(!txt || !txt[0]) return false;
else h = TxtSet.iSize;
if(TxtSet.Align & TXA_VCENTER) iy = y + h/3;
else if(TxtSet.Align & TXA_VBOTTOM) iy = y;
else iy = y + iround(h * 0.8);
ix = x;
if((TxtSet.Style & TXS_SUB) || (TxtSet.Style & TXS_SUPER)) h = iround((double)TxtSet.iSize * 0.8);
if(TxtSet.Style & TXS_SUB) {
if((TxtSet.Align & TXA_VCENTER) == TXA_VCENTER) iy +=un2iy(TxtSet.fSize*0.4);
else if((TxtSet.Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy += un2iy(TxtSet.fSize*0.2);
else if((TxtSet.Align & TXA_VTOP) == TXA_VTOP) iy += un2iy(TxtSet.fSize*.6);
}
else if(TxtSet.Style & TXS_SUPER) {
if((TxtSet.Align & TXA_VCENTER) == TXA_VCENTER) iy -= un2iy(TxtSet.fSize*0.4);
else if((TxtSet.Align & TXA_VBOTTOM) == TXA_VBOTTOM) iy -= un2iy(TxtSet.fSize*0.6);
else if((TxtSet.Align & TXA_VTOP) == TXA_VTOP) iy -= un2iy(TxtSet.fSize*0.2);
}
sprintf(output, "<text x=\"%d\" y=\"%d\" ", ix, iy);
if(fabs(TxtSet.RotBL) >.01 || fabs(TxtSet.RotCHAR) >.01) {
sprintf(tmptxt,"transform=\"rotate(%.0f,%d,%d)\" ", -TxtSet.RotBL, ix, iy);
strcat(output, tmptxt);
}
strcpy(tmptxt, "style=\"font-family:");
switch(TxtSet.Font) {
case FONT_TIMES: strcat(tmptxt, "Times;"); break;
case FONT_COURIER: strcat(tmptxt, "Courier;"); break;
default: strcat(tmptxt, "Helvetica;"); break;
}
if(TxtSet.Style & TXS_ITALIC) strcat(tmptxt, " font-style:italic;");
if(TxtSet.Style & TXS_BOLD) strcat(tmptxt, " font-weight:bold;");
if(TxtSet.Style & TXS_UNDERLINE) strcat(tmptxt, " text-decoration:underline;");
AddToOutput(tmptxt);
sprintf(tmptxt, " fill:%s; stroke:%s; ", ColName(TxtSet.ColTxt),
ColName(TxtSet.ColTxt));
AddToOutput(tmptxt);
sprintf(tmptxt, "font-size:%d; text-anchor:%s \">", h,
(TxtSet.Align & TXA_HRIGHT) ? "end" : (TxtSet.Align & TXA_HCENTER) ? "middle":"start");
AddToOutput(tmptxt);
nt = str2xml(txt);
if((TxtSet.Style & TXS_SUB) || (TxtSet.Style & TXS_SUPER)) {
for(i = strlen(nt)+6, nt[i+1]=0; i > 5; i--) {
nt[i] = nt[i-6];
}
nt[0] = '&'; nt[1] = 'n'; nt[2] = 'b';
nt[3] = 's'; nt[4] = 'p'; nt[5] = ';';
}
if((strlen(indent)+strlen(nt)+strlen(output)) <110) strcat(output, nt);
else {
fprintf(oFile, "%s%s\n", indent, output);
strcpy(output, nt);
}
if((strlen(indent) + strlen(output)) <104)
fprintf(oFile, "%s%s</text>\n", indent, output);
else {
fprintf(oFile, "%s%s\n", indent, output);
fprintf(oFile, "</text>\n");
}
return true;
}
bool
ExportSVG::oPolygon(POINT *pts, int cp, char *nam)
{
int i;
char tmptxt[40];
if(cp <3) return false;
if(hgo){
fprintf(oFile, "%s<g> <!-- polygon with pattern -->\n", indent);
Indent(true);
}
bOutputPending = false;
sprintf(output, "<polygon%s%s%s points=\"",
nam? " name=\"" : "", nam ? nam : "", nam ? "\"" : "");
for(i = 0; i < cp; i++) {
sprintf(tmptxt, "%d %d ", pts[i].x, pts[i].y);
AddToOutput(tmptxt);
}
i = strlen(output);
if(i) output[i-1] = 0;
strcat(output, "\" ");
sprintf(tmptxt, "style=\"fill:%s; ", ColName(dFillCol));
AddToOutput(tmptxt);
sprintf(tmptxt, "stroke:%s; ", ColName(dLineCol));
AddToOutput(tmptxt);
sprintf(tmptxt, "stroke-width:%d\"/>",iLineWidth);
AddToOutput(tmptxt);
if(output)fprintf(oFile, "%s%s\n", indent, output);
if(bOutputPending)Indent(false);
if(hgo) {
fprintf(oFile, "%s<g %s> <!-- hatch -->\n", indent, tHatchStyle);
Indent(true);
bUseGroupLine = true;
hgo->oPolygon(pts, cp);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -