DrGraph - SVG模块之一:显示与节点选择

DrGraph - SVG模块之一:显示与节点选择

  • 显示SVG
  • 编辑
  • 生成目标子集SVG

对于虚拟面板中的元件,以前采用FLASH技术实现相应显示与交互,通过ActionScript进行通信。现在看来,FLASH好象势微,使用起来有点麻烦,需要一些设置。其次,做FLASH的人也少了,后续也不太方便。
那就用SVG来进行改造。

显示SVG

将SVG解析置于DLL中,应用程序直接调用DLL完成解析并生成PNG,然后再画出显示。

UnicodeString filename = FResponseNode->AttributeValueByName("svgfileName");
TStringList * contents = new TStringList;
if(FileExists(filename))
	contents->LoadFromFile(filename);
UnicodeString firstLine = L"";
if(contents->Count)
	firstLine = contents->Strings[0].Trim();
bool drgraphFlag = firstLine.Pos(L"SVG by DrGraph");
int frameNumber = 1;
if(drgraphFlag)
	frameNumber = contents->Count - 1;

UnicodeString getType = FResponseNode->AttributeValueByName("get");
if(getType == L"frameNumber")
	FResponseNode->AddAttribute("frameNumber", frameNumber);
else {
	int frameIndex = FResponseNode->IntAttributeValueByName("frameIndex");
	if(drgraphFlag && frameNumber > 0) {
		while(frameIndex < 0)
			frameIndex += frameNumber;
		while(frameIndex >= frameNumber)
			frameIndex -= frameNumber;
		filename = THelper::File::GetPath_Debug() + ExtractFileName(filename);
		if(FileExists(filename))
			DeleteFile(filename);
		THelper::File::SetFileContent(filename,
			THelper::FormatString(L"\n%s", contents->Strings[frameIndex + 1]));
		Sleep(100);
	}
	TCbwSVG * svg = new TCbwSVG;
	UnicodeString dstFileName = THelper::FormatString(L"%s%s.png",
		THelper::File::GetPath_Debug(),
		THelper::File::ExtractPureFileName(filename)); // dstFileName
	double scale = 1;
	if (NSVGimage * image = svg->ParseFromFile(filename, "px", 96.0)) {
		if (NSVGrasterizer * rast = svg->NewRasterizer()) {
			if (unsigned char* img = (unsigned char *)malloc(image->width * image->height * 4)) {
				svg->Rasterize(rast,	// NSVGrasterizer* r
					image, // NSVGimage* image
					0, // float tx
					0, // float ty
					scale, // float scale
					img, // unsigned char* dst
					image->width * scale, // int w
					image->height * scale, // int h
					image->width * 4); // int stride
				svg->Save_Png(dstFileName, image->width, image->height, 4, img, image->width*4);
				free(img);
			}
			svg->Free(rast);
		}
		svg->Free(image);
	}
	delete svg;
	FResponseNode->AddAttribute("svgfileName", dstFileName);
}
delete contents;

其中,TCbwSVG直接包装C++的SVG库,省事。

class TCbwSVG {
private:
public:
	__fastcall TCbwSVG();
	__fastcall ~TCbwSVG();

	NSVGimage * __fastcall ParseFromFile(UnicodeString filename, UnicodeString units, double dpi);
	void __fastcall Rasterize(NSVGrasterizer* r, NSVGimage* image, float tx, float ty, float scale, unsigned char* dst,
		int w, int h, int stride);
	NSVGrasterizer * __fastcall NewRasterizer();
	void __fastcall Free(NSVGrasterizer * r);
	void __fastcall Free(NSVGimage * image);
	void __fastcall Free(NSVGparser * parser);

	int __fastcall Save_Png(UnicodeString filename, int w, int h, int comp, const void *data, int stride_in_bytes);
	int stbi_write_bmp(char const *filename, int w, int h, int comp, const void *data);
	int stbi_write_tga(char const *filename, int w, int h, int comp, const void *data);
};

显示Tiger.svg效果
DrGraph - SVG模块之一:显示与节点选择_第1张图片

编辑

在DrGraph软件中,无需象专业软件那样编辑SVG,能直观看到效果即可。
SVG文件为xml结构文本内容,可以先将XML转化为TreeView

void __fastcall CbwXmlNode::SaveToTreeNode(TTreeNode * node, UnicodeString textField, int operateKind) { //, bool bindFlag, bool refreshNodeFlag) {
	TTreeView * treeView = dynamic_cast<TTreeView *>(node->TreeView);
	if(!treeView)
		return;

	UnicodeString firstTextField = THelper::String::GetStringAt(textField, L";", 0);
	UnicodeString text = AttributeValueByName(firstTextField);
	TTreeNode * subTreeNode = node;
	if (text.Length()) {
		UnicodeString secondTextField = THelper::String::GetStringAt(textField, L";", 1);
		if(secondTextField.Length() && ContainAttribute(secondTextField)) {
			secondTextField = AttributeValueByName(secondTextField);
			if(secondTextField.Length())
				text = THelper::FormatString(L"%s〖%s〗", text, secondTextField);
		}
	} else
		text = GetHint(L"\n", true, DRGRAPH_FLAG_ONLY_MY_ATTRIBUTE);

	if(operateKind & DRGRAPH_VALUE_REFRESH_THIS_TREENODE)
		node->Text = text;
	else
		subTreeNode = treeView->Items->AddChild(node, text);
	if(operateKind & DRGRAPH_VALUE_BIND_NODEVALUE)
		subTreeNode->Data = this;
	operateKind = operateKind & (~DRGRAPH_VALUE_REFRESH_THIS_TREENODE);
	for (int i = 0; i < ElementNumber; ++i) {
		CbwXmlNode * subXmlNode = Elements(i);
		subXmlNode->SaveToTreeNode(subTreeNode, textField, operateKind);
	}
}

DrGraph - SVG模块之一:显示与节点选择_第2张图片

生成目标子集SVG

用户选择TreeView中的某些节点时,应该能及时更新相应显示内容,如
DrGraph - SVG模块之一:显示与节点选择_第3张图片
当然,通过临时SVG文件进行中转

void __fastcall TMainForm::TreeView_XmlChange(TObject *Sender, TTreeNode *Node)
{
	TList * selections = new TList;
	TreeView_Xml->GetSelections(selections);
	for(int i = 0; i < TreeView_Xml->Items->Count; ++i)
		TreeView_Xml->Items->Item[i]->StateIndex = NORMAL_STATE;
	for(int i = 0; i < selections->Count; ++i) {
		TTreeNode * node = (TTreeNode *)(selections->Items[i]);
		if(node->StateIndex == SELECT_STATE)
			continue;
		node->StateIndex = SELECT_STATE;
		TTreeNode * parent = node->Parent;	
		while(parent) {
			if(parent->StateIndex == NORMAL_STATE) {	
				parent->StateIndex = SELECT_STATE;
				int index = selections->IndexOf(parent);
				if(index == -1)
					selections->Insert(i, parent);
			}
			parent = parent->Parent;
		}
	}

	UnicodeString info = L"";
	for(int i = 0; i < selections->Count; ++i) {
		TTreeNode * node = (TTreeNode *)(selections->Items[i]);
		info += localGetTreeNodeText(node, selections);
	}
	UnicodeString svgFileName = THelper::File::GetPath_Debug() + L"debug.svg";
	if(FileExists(svgFileName))
		DeleteFile(svgFileName);
	THelper::File::SetFileContent(svgFileName, info);
	UnicodeString fileName = GlobalImageObject->OnCommand(THelper::FormatString(L"", svgFileName), "svgfileName");
	if(FileExists(fileName)) {
		CBW_CAST(TCbwImage, image, TreeView_Xml->Tag);
		if(image) {
			image->RefreshSVG(fileName);
			image->Dispear();
			image->Draw();
			FCurrentForm->RefreshCurrentScreen();
		}
	}
	delete selections;
}

上图示例生成临时SVG为

 <svg version='1.1' viewBox='0 0 900 900' xmlns='http://www.w3.org/2000/svg' >
  <g fill='none' id='g4' transform='matrix(1.7656463,0,0,1.7656463,324.90716,255.00942)' >
    <g fill='#cc7226' id='g318' >
      <path d='m-58.6,14.4s-3.2-21.2-0.8-25.6c0,0,10.8-10,10.4-13.6,0,0-0.4-18-1.6-18.8s-8.8-6.8-14.8-0.4c0,0-10.4,18-9.6,24.4v2s-7.6-0.4-9.2,1.6c0,0-1.2,5.2-2.4,5.6,0,0-2.8,2.4-0.8,5.2,0,0-2,2.4-1.6,6.4l7.6,4s2,14.4,12.8,19.6c4.836,2.329,8-4.4,10-10.4z' id='path320' />
    g>
    <g fill='#FFF' id='g322' >
      <path d='m-59.6,12.56s-2.88-19.08-0.72-23.04c0,0,9.72-9,9.36-12.24,0,0-0.36-16.2-1.44-16.92s-7.92-6.12-13.32-0.36c0,0-9.36,16.2-8.64,21.96v1.8s-6.84-0.36-8.28,1.44c0,0-1.08,4.68-2.16,5.04,0,0-2.52,2.16-0.72,4.68,0,0-1.8,2.16-1.44,5.76l6.84,3.6s1.8,12.96,11.52,17.64c4.352,2.095,7.2-3.96,9-9.36z' id='path324' />
    g>
    <g fill='#eb955c' id='g326' >
      <path d='m-51.05-42.61c-1.09-0.86-8.58-6.63-14.43-0.39,0,0-10.14,17.55-9.36,23.79v1.95s-7.41-0.39-8.97,1.56c0,0-1.17,5.07-2.34,5.46,0,0-2.73,2.34-0.78,5.07,0,0-1.95,2.34-1.56,6.24l7.41,3.9s1.95,14.04,12.48,19.11c4.714,2.27,7.8-4.29,9.75-10.14,0,0-3.12-20.67-0.78-24.96,0,0,10.53-9.75,10.14-13.26,0,0-0.39-17.55-1.56-18.33z' id='path328' />
    g>
    <g fill='#f2b892' id='g330' >
      <path d='m-51.5-41.62c-0.98-0.92-8.36-6.46-14.06-0.38,0,0-9.88,17.1-9.12,23.18v1.9s-7.22-0.38-8.74,1.52c0,0-1.14,4.94-2.28,5.32,0,0-2.66,2.28-0.76,4.94,0,0-1.9,2.28-1.52,6.08l7.22,3.8s1.9,13.68,12.16,18.62c4.594,2.212,7.6-4.18,9.5-9.88,0,0-3.04-20.14-0.76-24.32,0,0,10.26-9.5,9.88-12.92,0,0-0.38-17.1-1.52-17.86z' id='path332' />
    g>
    <g fill='#f8dcc8' id='g334' >
      <path d='m-51.95-40.63c-0.87-0.98-8.14-6.29-13.69-0.37,0,0-9.62,16.65-8.88,22.57v1.85s-7.03-0.37-8.51,1.48c0,0-1.11,4.81-2.22,5.18,0,0-2.59,2.22-0.74,4.81,0,0-1.85,2.22-1.48,5.92l7.03,3.7s1.85,13.32,11.84,18.13c4.473,2.154,7.4-4.07,9.25-9.62,0,0-2.96-19.61-0.74-23.68,0,0,9.99-9.25,9.62-12.58,0,0-0.37-16.65-1.48-17.39z' id='path336' />
    g>
    <g fill='#FFF' id='g338' >
      <path d='m-59.6,12.46s-2.88-18.98-0.72-22.94c0,0,9.72-9,9.36-12.24,0,0-0.36-16.2-1.44-16.92-0.76-1.04-7.92-6.12-13.32-0.36,0,0-9.36,16.2-8.64,21.96v1.8s-6.84-0.36-8.28,1.44c0,0-1.08,4.68-2.16,5.04,0,0-2.52,2.16-0.72,4.68,0,0-1.8,2.16-1.44,5.76l6.84,3.6s1.8,12.96,11.52,17.64c4.352,2.095,7.2-4.06,9-9.46z' id='path340' />
    g>
    <g fill='#CCC' id='g342' >
      <path d='m-62.7,6.2s-21.6-10.2-22.5-11c0,0,9.1,8.2,9.9,8.2s12.6,2.8,12.6,2.8z' id='path344' />
    g>
    <g fill='#000' id='g346' >
      <path d='m-79.8,0s18.4,3.6,18.4,8c0,2.912-0.243,16.331-5.6,14.8-8.4-2.4-4.8-16.8-12.8-22.8z' id='path348' />
    g>
    <g fill='#99cc32' id='g350' >
      <path d='m-71.4,3.8s8.978,1.474,10,4.2c0.6,1.6,1.263,9.908-4.2,11-4.552,0.911-6.782-9.31-5.8-15.2z' id='path352' />
    g>
    <g fill='#000' id='g354' >
      <path d='m14.595,46.349c-0.497-1.742,0.814-1.611,2.605-2.149,2-0.6,14.2-4.4,15-7s14,1.8,14,1.8c1.8,0.8,6.2,3.4,6.2,3.4,4.8,1.2,11.4,1.6,11.4,1.6,2.4,1,5.8,3.8,5.8,3.8,14.6,10.2,27.001,3,27.001,3,19.999-6.6,13.999-23.8,13.999-23.8-3-9,0.2-12.4,0.2-12.4,0.2-3.8,7.4,2.6,7.4,2.6,2.6,4.2,3.4,9.2,3.4,9.2,8,11.2,4.6-6.6,4.6-6.6,0.2-1-2.6-4.6-2.6-5.8s-1.8-4.6-1.8-4.6c-3-3.4-0.6-10.4-0.6-10.4,1.8-13.8-0.4-12-0.4-12-1.2-1.8-10.4,8.2-10.4,8.2-2.2,3.4-8.2,5-8.2,5-2.799,1.8-6.199,0.4-6.199,0.4-2.6-0.4-8.2,6.6-8.2,6.6,2.8-0.2,5.2,4.2,7.6,4.4s4.2-2.4,5.799-3c1.6-0.6,4.4,5.2,4.4,5.2,0.4,2.6-5.2,7.4-5.2,7.4-0.4,4.6-1.999,3-1.999,3-3-0.6-4.2,3.2-5.2,7.8s-5.2,5-5.2,5c-1.6,7.4-2.801,4.4-2.801,4.4-0.2-5.6-6.2,0.2-6.2,0.2-1.2,2-5.8-0.2-5.8-0.2-6.8-2-4.4-4-4.4-4,1.8-2.2,13,0,13,0,2.2-1.6-5.8-5.6-5.8-5.6-0.6-1.8,0.4-6.2,0.4-6.2,1.2-3.2,8-8.8,8-8.8,9.401-1.2,6.601-2.8,6.601-2.8-6.2-5.2-12.001,2.4-12.001,2.4-2.2,6.2-19.6,21.2-19.6,21.2-4.8,3.4-2.2-3.4-6.2,0s-24.6-5.6-24.6-5.6c-11.562-1.193-14.294,14.549-17.823,11.429,0,0,5.418,8.52,3.818,2.92z' id='path356' />
    g>
    <g fill='#000' id='g358' >
      <path d='m209.4-120s-25.6,8-28.4,26.8c0,0-2.4,22.8,18,40.4,0,0,0.4,6.4,2.4,9.6,0,0-1.6,4.8,17.2-2.8l27.2-8.4s6.4-2.4,11.6-11.2,20.4-27.6,16.8-52.8c0,0,1.2-11.2-4.8-11.6,0,0-8.4-1.6-15.6,6,0,0-6.8,3.2-9.2,2.8l-35.2,1.2z' id='path360' />
    g>
    <g fill='#000' id='g362' >
      <path d='m264.02-120.99s2.1-8.93-2.74-4.09c0,0-7.04,5.72-14.52,5.72,0,0-14.52,2.2-18.92,15.4,0,0-3.96,26.84,3.96,32.56,0,0,4.84,7.48,11.88,0.88s22.54-36.83,20.34-50.47z' id='path364' />
    g>
    <g fill='#323232' id='g366' >
      <path d='m263.65-120.63s2.09-8.75-2.66-3.99c0,0-6.92,5.61-14.26,5.61,0,0-14.26,2.16-18.58,15.12,0,0-3.89,26.354,3.89,31.97,0,0,4.75,7.344,11.66,0.864,6.92-6.48,22.11-36.184,19.95-49.574z' id='path368' />
    g>
  g>
 svg>

在此基础上,可进行SVG元件的属性设计。

你可能感兴趣的:(DrGraph,原理示教,图像分析,图像分析,电路分析)