Implement block-diagram schema generation in svg or postscript format. More...
#include <stdio.h>
#include <ctype.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <string.h>
#include <ostream>
#include <sstream>
#include <set>
#include <utility>
#include <map>
#include <stack>
#include <string>
#include "boxes.hh"
#include "ppbox.hh"
#include "prim2.hh"
#include <vector>
#include "devLib.h"
#include "xtended.hh"
#include "occurrences.hh"
#include "boxcomplexity.h"
#include "schema.h"
#include "drawschema.hh"
#include "compatibility.hh"
#include "names.hh"
Go to the source code of this file.
Defines | |
#define | linkcolor "#003366" |
#define | normalcolor "#4B71A1" |
#define | uicolor "#477881" |
#define | slotcolor "#47945E" |
#define | numcolor "#f44800" |
Functions | |
static void | writeSchemaFile (Tree bd) |
Write a top level diagram. | |
static schema * | generateDiagramSchema (Tree t) |
Generate an appropriate schema according to the type of block diagram. | |
static schema * | generateInsideSchema (Tree t) |
Generate the inside schema of a block diagram according to its type. | |
static void | scheduleDrawing (Tree t) |
Schedule a makeBlockSchema diagram to be drawn. | |
static bool | pendingDrawing (Tree &t) |
Retrieve next block diagram that must be drawn. | |
static schema * | generateAbstractionSchema (schema *x, Tree t) |
Generate an abstraction schema by placing in sequence the input slots and the body. | |
static schema * | generateOutputSlotSchema (Tree a) |
Generate a 0->1 block schema for an output slot. | |
static schema * | generateInputSlotSchema (Tree a) |
Generate a 1->0 block schema for an input slot. | |
static schema * | generateBargraphSchema (Tree t) |
Generate a 1->1 block schema for a user interface bargraph. | |
static schema * | generateUserInterfaceSchema (Tree t) |
Generate a 0->1 block schema for a user interface element. | |
static char * | legalFileName (Tree t, int n, char *dst) |
Transform the definition name property of tree <t> into a legal file name. | |
static int | cholddir () |
Switch back to the previously stored current directory. | |
static int | mkchdir (const char *dirname) |
Create a new directory in the current one to store the diagrams. | |
void | drawSchema (Tree bd, const char *projname, const char *dev) |
The entry point to generate from a block diagram as a set of svg files stored in the directory "<projname>-svg/" or "<projname>-ps/" depending of <dev>. | |
Variables | |
int | gFoldThreshold |
static Occurrences * | gOccurrences |
static bool | sFoldingFlag |
static stack< Tree > | gPendingExp |
static set< Tree > | gDrawnExp |
static const char * | gDevSuffix |
static char | gCurrentDir [512] |
static string | gSchemaFileName |
static map< Tree, string > | gBackLink |
Implement block-diagram schema generation in svg or postscript format.
The result is a folder containing one or more schema files in svg or ps format. Complex block-diagrams are automatically splitted.
Definition in file drawschema.cpp.
#define linkcolor "#003366" |
Definition at line 112 of file drawschema.cpp.
Referenced by generateDiagramSchema().
#define normalcolor "#4B71A1" |
Definition at line 113 of file drawschema.cpp.
Referenced by generateInsideSchema().
#define numcolor "#f44800" |
Definition at line 116 of file drawschema.cpp.
Referenced by generateInsideSchema().
#define slotcolor "#47945E" |
Definition at line 115 of file drawschema.cpp.
Referenced by generateInputSlotSchema(), and generateOutputSlotSchema().
#define uicolor "#477881" |
Definition at line 114 of file drawschema.cpp.
Referenced by generateBargraphSchema(), and generateUserInterfaceSchema().
static int cholddir | ( | ) | [static] |
Switch back to the previously stored current directory.
Definition at line 279 of file drawschema.cpp.
References gCurrentDir.
Referenced by drawSchema().
00280 { 00281 if (chdir(gCurrentDir) == 0) { 00282 return 0; 00283 } else { 00284 perror("cholddir"); 00285 exit(errno); 00286 } 00287 }
void drawSchema | ( | Tree | bd, | |
const char * | projname, | |||
const char * | dev | |||
) |
The entry point to generate from a block diagram as a set of svg files stored in the directory "<projname>-svg/" or "<projname>-ps/" depending of <dev>.
Definition at line 158 of file drawschema.cpp.
References boxComplexity(), cholddir(), gDevSuffix, gFoldThreshold, mkchdir(), pendingDrawing(), scheduleDrawing(), sFoldingFlag, and writeSchemaFile().
Referenced by main(), and printDocDgm().
00159 { 00160 gDevSuffix = dev; 00161 sFoldingFlag = boxComplexity(bd) > gFoldThreshold; 00162 00163 mkchdir(projname); // create a directory to store files 00164 00165 scheduleDrawing(bd); // schedule the initial drawing 00166 00167 Tree t; while (pendingDrawing(t)) { 00168 writeSchemaFile(t); // generate all the pending drawing 00169 } 00170 00171 cholddir(); // return to current directory 00172 }
Generate an abstraction schema by placing in sequence the input slots and the body.
Definition at line 497 of file drawschema.cpp.
References generateDiagramSchema(), generateInputSlotSchema(), isBoxSymbolic(), makeParSchema(), and makeSeqSchema().
Referenced by generateInsideSchema().
00498 { 00499 Tree a,b; 00500 00501 while (isBoxSymbolic(t,a,b)) { 00502 x = makeParSchema(x, generateInputSlotSchema(a)); 00503 t = b; 00504 } 00505 return makeSeqSchema(x, generateDiagramSchema(t)); 00506 }
Generate a 1->1 block schema for a user interface bargraph.
Definition at line 459 of file drawschema.cpp.
References makeBlockSchema(), and uicolor.
Referenced by generateInsideSchema().
00460 { 00461 stringstream s; 00462 s << boxpp(t); 00463 00464 return makeBlockSchema(1, 1, s.str(), uicolor, ""); 00465 }
Generate an appropriate schema according to the type of block diagram.
When folding is requiered, instead of going down block-diagrams with a name, schedule them for an individual file.
Definition at line 324 of file drawschema.cpp.
References boxComplexity(), gDevSuffix, generateInsideSchema(), getBoxType(), getDefNameProperty(), isBoxSlot(), legalFileName(), linkcolor, makeBlockSchema(), makeDecorateSchema(), scheduleDrawing(), sFoldingFlag, and tree2str().
Referenced by generateAbstractionSchema(), and generateInsideSchema().
00325 { 00326 Tree id; 00327 int ins, outs; 00328 00329 //cerr << t << " generateDiagramSchema " << boxpp(t)<< endl; 00330 00331 if (getDefNameProperty(t, id)) { 00332 stringstream s; s << tree2str(id); 00333 //cerr << t << "\tNAMED : " << s.str() << endl; 00334 } 00335 00336 if ( sFoldingFlag && /*(gOccurrences->getCount(t) > 0) &&*/ 00337 (boxComplexity(t) > 2) && getDefNameProperty(t, id)) { 00338 char temp[1024]; 00339 getBoxType(t, &ins, &outs); 00340 stringstream s, l; 00341 s << tree2str(id); 00342 l << legalFileName(t,1024,temp) << "." << gDevSuffix; 00343 scheduleDrawing(t); 00344 return makeBlockSchema(ins, outs, s.str(), linkcolor, l.str()); 00345 00346 } else if (getDefNameProperty(t, id) && ! isBoxSlot(t)) { 00347 // named case : not a slot, with a name 00348 // draw a line around the object with its name 00349 stringstream s; s << tree2str(id); 00350 return makeDecorateSchema(generateInsideSchema(t), 10, s.str()); 00351 00352 } else { 00353 // normal case 00354 return generateInsideSchema(t); 00355 } 00356 }
Generate a 1->0 block schema for an input slot.
Definition at line 472 of file drawschema.cpp.
References getDefNameProperty(), makeBlockSchema(), slotcolor, and tree2str().
Referenced by generateAbstractionSchema(), and generateInsideSchema().
00473 { 00474 Tree id; assert(getDefNameProperty(a, id)); 00475 stringstream s; s << tree2str(id); 00476 return makeBlockSchema(1, 0, s.str(), slotcolor, ""); 00477 }
Generate the inside schema of a block diagram according to its type.
Definition at line 364 of file drawschema.cpp.
References xtended::arity(), ffarity(), ffname(), generateAbstractionSchema(), generateBargraphSchema(), generateDiagramSchema(), generateInputSlotSchema(), generateOutputSlotSchema(), generateUserInterfaceSchema(), getDefNameProperty(), getUserData(), isBoxButton(), isBoxCheckbox(), isBoxCut(), isBoxFConst(), isBoxFFun(), isBoxFVar(), isBoxHBargraph(), isBoxHGroup(), isBoxHSlider(), isBoxInt(), isBoxMerge(), isBoxNumEntry(), isBoxPar(), isBoxPrim0(), isBoxPrim1(), isBoxPrim2(), isBoxPrim3(), isBoxPrim4(), isBoxPrim5(), isBoxReal(), isBoxRec(), isBoxSeq(), isBoxSlot(), isBoxSplit(), isBoxSymbolic(), isBoxTGroup(), isBoxVBargraph(), isBoxVGroup(), isBoxVSlider(), isBoxWire(), makeBlockSchema(), makeCableSchema(), makeCutSchema(), makeDecorateSchema(), makeMergeSchema(), makeParSchema(), makeRecSchema(), makeSeqSchema(), makeSplitSchema(), xtended::name(), name(), normalcolor, numcolor, prim0name(), prim1name(), prim2name(), prim3name(), prim4name(), prim5name(), print(), and tree2str().
Referenced by generateDiagramSchema(), and writeSchemaFile().
00365 { 00366 Tree a, b, ff, l, type,name,file; 00367 int i; 00368 double r; 00369 prim0 p0; 00370 prim1 p1; 00371 prim2 p2; 00372 prim3 p3; 00373 prim4 p4; 00374 prim5 p5; 00375 00376 00377 xtended* xt = (xtended*)getUserData(t); 00378 00379 if (xt) { return makeBlockSchema(xt->arity(), 1, xt->name(), normalcolor, ""); } 00380 00381 else if (isBoxInt(t, &i)) { stringstream s; s << i; return makeBlockSchema(0, 1, s.str(), numcolor, "" ); } 00382 else if (isBoxReal(t, &r)) { stringstream s; s << r; return makeBlockSchema(0, 1, s.str(), numcolor, "" ); } 00383 else if (isBoxWire(t)) { return makeCableSchema(); } 00384 else if (isBoxCut(t)) { return makeCutSchema(); } 00385 00386 else if (isBoxPrim0(t, &p0)) { return makeBlockSchema(0, 1, prim0name(p0), normalcolor, ""); } 00387 else if (isBoxPrim1(t, &p1)) { return makeBlockSchema(1, 1, prim1name(p1), normalcolor, ""); } 00388 else if (isBoxPrim2(t, &p2)) { return makeBlockSchema(2, 1, prim2name(p2), normalcolor, ""); } 00389 else if (isBoxPrim3(t, &p3)) { return makeBlockSchema(3, 1, prim3name(p3), normalcolor, ""); } 00390 else if (isBoxPrim4(t, &p4)) { return makeBlockSchema(4, 1, prim4name(p4), normalcolor, ""); } 00391 else if (isBoxPrim5(t, &p5)) { return makeBlockSchema(5, 1, prim5name(p5), normalcolor, ""); } 00392 00393 else if (isBoxFFun(t, ff)) { return makeBlockSchema(ffarity(ff), 1, ffname(ff), normalcolor, ""); } 00394 else if (isBoxFConst(t, type,name,file)) { return makeBlockSchema(0, 1, tree2str(name), normalcolor, ""); } 00395 else if (isBoxFVar (t, type, name,file)) { return makeBlockSchema(0, 1, tree2str(name), normalcolor, ""); } 00396 00397 else if (isBoxButton(t)) { return generateUserInterfaceSchema(t); } 00398 else if (isBoxCheckbox(t)) { return generateUserInterfaceSchema(t); } 00399 else if (isBoxVSlider(t)) { return generateUserInterfaceSchema(t); } 00400 else if (isBoxHSlider(t)) { return generateUserInterfaceSchema(t); } 00401 else if (isBoxNumEntry(t)) { return generateUserInterfaceSchema(t); } 00402 else if (isBoxVBargraph(t)) { return generateBargraphSchema(t); } 00403 else if (isBoxHBargraph(t)) { return generateBargraphSchema(t); } 00404 00405 // don't draw group rectangle when labels are empty (ie "") 00406 else if (isBoxVGroup(t,l,a)) { stringstream s; s << "vgroup(" << tree2str(l) << ")"; 00407 schema* r = generateDiagramSchema(a); 00408 return makeDecorateSchema(r, 10, s.str()); } 00409 else if (isBoxHGroup(t,l,a)) { stringstream s; s << "hgroup(" << tree2str(l) << ")"; 00410 schema* r = generateDiagramSchema(a); 00411 return makeDecorateSchema(r, 10, s.str()); } 00412 else if (isBoxTGroup(t,l,a)) { stringstream s; s << "tgroup(" << tree2str(l) << ")"; 00413 schema* r = generateDiagramSchema(a); 00414 return makeDecorateSchema(r, 10, s.str()); } 00415 00416 else if (isBoxSeq(t, a, b)) { return makeSeqSchema(generateDiagramSchema(a), generateDiagramSchema(b)); } 00417 else if (isBoxPar(t, a, b)) { return makeParSchema(generateDiagramSchema(a), generateDiagramSchema(b)); } 00418 else if (isBoxSplit(t, a, b)) { return makeSplitSchema(generateDiagramSchema(a), generateDiagramSchema(b)); } 00419 else if (isBoxMerge(t, a, b)) { return makeMergeSchema(generateDiagramSchema(a), generateDiagramSchema(b)); } 00420 else if (isBoxRec(t, a, b)) { return makeRecSchema(generateDiagramSchema(a), generateDiagramSchema(b)); } 00421 00422 else if (isBoxSlot(t, &i)) { return generateOutputSlotSchema(t); } 00423 else if (isBoxSymbolic(t,a,b)) { 00424 Tree id; 00425 if (getDefNameProperty(t, id)) { 00426 return generateAbstractionSchema(generateInputSlotSchema(a), b); 00427 } else { 00428 return makeDecorateSchema(generateAbstractionSchema(generateInputSlotSchema(a), b), 10, "Abstraction"); 00429 } 00430 } 00431 00432 else { 00433 00434 fprintf(stderr, "Internal Error, box expression not recognized : "); print(t, stderr); fprintf(stderr, "\n"); 00435 exit(1); 00436 00437 } 00438 }
Generate a 0->1 block schema for an output slot.
Definition at line 484 of file drawschema.cpp.
References getDefNameProperty(), makeBlockSchema(), slotcolor, and tree2str().
Referenced by generateInsideSchema().
00485 { 00486 Tree id; assert(getDefNameProperty(a, id)); 00487 stringstream s; s << tree2str(id); 00488 return makeBlockSchema(0, 1, s.str(), slotcolor, ""); 00489 }
Generate a 0->1 block schema for a user interface element.
Definition at line 446 of file drawschema.cpp.
References makeBlockSchema(), and uicolor.
Referenced by generateInsideSchema().
00447 { 00448 stringstream s; 00449 s << boxpp(t); 00450 00451 return makeBlockSchema(0, 1, s.str(), uicolor, ""); 00452 }
static char * legalFileName | ( | Tree | t, | |
int | n, | |||
char * | dst | |||
) | [static] |
Transform the definition name property of tree <t> into a legal file name.
The resulting file name is stored in <dst> a table of at least <n> chars. Returns the <dst> pointer for convenience.
Definition at line 296 of file drawschema.cpp.
References getDefNameProperty(), and tree2str().
Referenced by generateDiagramSchema(), and writeSchemaFile().
00297 { 00298 Tree id; 00299 int i=0; 00300 if (getDefNameProperty(t, id)) { 00301 const char* src = tree2str(id); 00302 for (i=0; isalnum(src[i]) && i<16; i++) { 00303 dst[i] = src[i]; 00304 } 00305 } 00306 dst[i] = 0; 00307 if (strcmp(dst, "process") != 0) { 00308 // if it is not process add the hex address to make the name unique 00309 snprintf(&dst[i], n-i, "-%p", t); 00310 } 00311 return dst; 00312 }
static int mkchdir | ( | const char * | dirname | ) | [static] |
Create a new directory in the current one to store the diagrams.
The current directory is saved to be later restaured.
Definition at line 259 of file drawschema.cpp.
References gCurrentDir.
Referenced by drawSchema().
00260 { 00261 //cerr << "mkchdir of " << dirname << endl; 00262 if (getcwd(gCurrentDir, 512) != 0) { 00263 int status = mkdir(dirname, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); 00264 if (status == 0 || errno == EEXIST) { 00265 if (chdir(dirname) == 0) { 00266 return 0; 00267 } 00268 } 00269 } 00270 perror("mkchdir"); 00271 exit(errno); 00272 //return errno; 00273 }
static bool pendingDrawing | ( | Tree & | t | ) | [static] |
Retrieve next block diagram that must be drawn.
Definition at line 199 of file drawschema.cpp.
References gPendingExp.
Referenced by drawSchema().
00200 { 00201 if (gPendingExp.empty()) return false; 00202 t = gPendingExp.top(); 00203 gPendingExp.pop(); 00204 return true; 00205 }
static void scheduleDrawing | ( | Tree | t | ) | [static] |
Schedule a makeBlockSchema diagram to be drawn.
Definition at line 187 of file drawschema.cpp.
References gBackLink, gDrawnExp, gPendingExp, and gSchemaFileName.
Referenced by drawSchema(), and generateDiagramSchema().
00188 { 00189 if (gDrawnExp.find(t) == gDrawnExp.end()) { 00190 gDrawnExp.insert(t); 00191 gBackLink.insert(make_pair(t,gSchemaFileName)); // remember the enclosing filename 00192 gPendingExp.push(t); 00193 } 00194 }
static void writeSchemaFile | ( | Tree | bd | ) | [static] |
Write a top level diagram.
A top level diagram is decorated with its definition name property and is drawn in an individual file
Definition at line 216 of file drawschema.cpp.
References schema::draw(), gBackLink, gDevSuffix, generateInsideSchema(), getDefNameProperty(), gSchemaFileName, schema::height(), kLeftRight, legalFileName(), makeTopSchema(), schema::place(), tree(), tree2str(), unique(), and schema::width().
Referenced by drawSchema().
00217 { 00218 Tree id; 00219 schema* ts; 00220 00221 char temp[1024]; 00222 00223 gOccurrences = new Occurrences(bd); 00224 00225 bool hasname = getDefNameProperty(bd, id); 00226 00227 //assert(hasname); 00228 if (!hasname) { 00229 // create an arbitrary name 00230 id = tree(Node(unique("diagram_"))); 00231 } 00232 00233 // generate legal file name for the schema 00234 stringstream s1; s1 << legalFileName(bd, 1024, temp) << "." << gDevSuffix; 00235 gSchemaFileName = s1.str(); 00236 00237 // generate the label of the schema 00238 stringstream s2; s2 << tree2str(id); 00239 string link = gBackLink[bd]; 00240 ts = makeTopSchema(generateInsideSchema(bd), 20, s2.str(), link); 00241 // draw to the device defined by gDevSuffix 00242 if (strcmp(gDevSuffix, "svg") == 0) { 00243 SVGDev dev(s1.str().c_str(), ts->width(), ts->height()); 00244 ts->place(0,0, kLeftRight); 00245 ts->draw(dev); 00246 } else { 00247 PSDev dev(s1.str().c_str(), ts->width(), ts->height()); 00248 ts->place(0,0, kLeftRight); 00249 ts->draw(dev); 00250 } 00251 }
Definition at line 133 of file drawschema.cpp.
Referenced by scheduleDrawing(), and writeSchemaFile().
char gCurrentDir[512] [static] |
Definition at line 131 of file drawschema.cpp.
Referenced by cholddir(), and mkchdir().
const char* gDevSuffix [static] |
Definition at line 130 of file drawschema.cpp.
Referenced by drawSchema(), generateDiagramSchema(), and writeSchemaFile().
Definition at line 129 of file drawschema.cpp.
Referenced by scheduleDrawing().
int gFoldThreshold |
Definition at line 124 of file main.cpp.
Referenced by drawSchema(), and process_cmdline().
Occurrences* gOccurrences [static] |
Definition at line 126 of file drawschema.cpp.
stack<Tree> gPendingExp [static] |
Definition at line 128 of file drawschema.cpp.
Referenced by pendingDrawing(), and scheduleDrawing().
string gSchemaFileName [static] |
Definition at line 132 of file drawschema.cpp.
Referenced by scheduleDrawing(), and writeSchemaFile().
bool sFoldingFlag [static] |
Definition at line 127 of file drawschema.cpp.
Referenced by drawSchema(), and generateDiagramSchema().