1. Protel库格式
Protel库文件后缀名为.lib,可存为binary与ascii两种格式,本文针对ascii格式的Protel库文件进行导入处理。对于binary格式的Protel库文件,需进行相应处理,请参阅《图形博士(通用平台系统)-使用手册.pdf》中的相关说明。
1.2 Ascii格式的Protel库文件
用任意文本编辑器打开ascii格式的Protel库文件。
Protel for Windows - Schematic Library Editor Ascii File Version 1.2 - 2.0
5348
Organization
Miscellaneous Devices
0 0
End
[Font_Table]
3
10 0 0 0 0 0 Times New Roman
8 0 0 0 0 0 Arial
8 0 0 0 0 0 Times New Roman
EndFont
Library 0 9 0 1 0 0 15269887 1 10 1 10 1000 800 0 0
269
Component
1
1
RCA Connector
P?
RCA
Part
0 0
Pin 0 0 4 0 0 0 20 20 -10 0 0 'X' '1'
Pin 0 0 4 0 0 0 20 10 -20 3 0 'Y' '2'
Ellipse 10 -10 2 2 1 16711680 16711680 1 0
EllipticalArc 10 -10 10 10 1 0.000 0.000 16711680 0
EndNormalPart
EndDeMorganPart
EndIEEEPart
EndComponent
…
|
可以猜测,凡是以End开头的单词,将表示某一个部分的结束。
大致推导其中内容含义如下:
1. 库头部分:
Protel for Windows - Schematic Library Editor Ascii File Version 1.2 - 2.0
5348
Organization
Miscellaneous Devices
0 0
End
|
本部分在导入时可以忽略不处理。
2. 字体表
[Font_Table]
3
10 0 0 0 0 0 Times New Roman
8 0 0 0 0 0 Arial
8 0 0 0 0 0 Times New Roman
EndFont
|
其中[Font_Table]为开始,EndFont为结束。
第二行的数字表示共有多少种字体
第三行以后到EndFont之前,一行表示一种字体。每行有6个整数,最后为字体名称。第一个数表示字体大小,后续5个应为诸如字形、风格、颜色等,如果不处理后5个整数,大致能满足要求。
3. 元件节
本节第一二行内容
Library 0 9 0 1 0 0 15269887 1 10 1 10 1000 800 0 0
269
|
其中第一行表示库实质内容开始,第二行表示本库中共有的元件数目。
本节后续内容将以元件为单位重复,各元件内容结构如下
Component
1
1
RCA Connector
P?
RCA
Part
0 0
Pin 0 0 4 0 0 0 20 20 -10 0 0 'X' '1'
Pin 0 0 4 0 0 0 20 10 -20 3 0 'Y' '2'
Ellipse 10 -10 2 2 1 16711680 16711680 1 0
EllipticalArc 10 -10 10 10 1 0.000 0.000 16711680 0
EndNormalPart
EndDeMorganPart
EndIEEEPart
EndComponent
…
|
其第1行表示元件开始
第2、3行表示组及其序号
第5行表示元件描述
第18行表示元件的缺省名称
第20行表示元件的类型名称
第21行表示开始说明该元件各子图元
第22行,0 0不明白其中含义,不过也无关紧要。
后续各行直至End…Part之间,一行说明一个子图元。这是元件图形模型的核心所在。
2. Protel库导入
void __fastcall TLibEditForm::LoadProtelLibFile(AnsiString fileName)
{
if(!FileExists(fileName)) return;
TStrings * list = new TStringList;
list->LoadFromFile(fileName);
int count = list->Count;
for(int i = 0; i < count; ++i)
{
AnsiString str = list->Strings[i].Trim();
if(SameText(str, "Component"))
ReadComponent(list, i);
else if(SameText(str, "[Font_Table]"))
ReadFont(list, i);
}
delete list;
}
|
不需要处理
读入处理到[Font_Table]时,进入字体处理
void __fastcall ReadFont(TStrings * list, int& index)
{
CBW_ITERATOR(vector<TFont *>, ProtelFontList)
{
TFont * font = *it;
if(font)
{
::DeleteObject(font->Handle);
delete font;
}
}
ProtelFontList.clear();
++index;
AnsiString str = list->Strings[index++];
int fontNumber = str.ToInt();
FlushVector(ProtelFontList, true);
for(int i = 0; i < fontNumber; ++i)
{
str = list->Strings[index++];
TStrings * fontContents = String2List(str, " ");
if(fontContents->Count > 6)
{
AnsiString fontName = fontContents->Strings[6];
for(int j = 7; j < fontContents->Count; ++j)
fontName += " " + fontContents->Strings[j];
TFont * font = new TFont;
font->Name = fontName;
font->Size = fontContents->Strings[0].ToInt();
ProtelFontList.push_back(font);
}
delete fontContents;
}
++index;
}
|
读入遇到Component时,进行元件处理
void __fastcall TLibEditForm::ReadComponent(TStrings * list, int& index)
{
NewUnit();
TText * unitName = cCurrentUnit->UnitName;
unitName->Top = 385;
unitName->Left = 400;
int count = list->Count;
bool partFlag = false;
for(int i = index; i < count; ++i)
{
AnsiString str = list->Strings[i].Trim();
CBW_CONDITION_CONTINUE(str.Length() == 0);
if(SameText(str, "Part")) partFlag = true;
int offset = i - index;
if(offset > 19 && SameText(str, "EndComponent"))
{
index = i;
break;
}
if(offset == 4)
cCurrentUnit->Description = str;
else if(offset == 17)
cCurrentUnit->UnitName->Caption = str;
else if(offset == 19)
{
cCurrentUnit->TypeName = str;
TreeView1->Items->Item[TreeView1->Items->Count - 1]->Text = str;
}
else if(partFlag)
AddProtelLibObject(str);
}
if(cCurrentUnit->MetaNumber == 1)
DeleteUnit();
}
|
具体处理各子图元
void __fastcall TLibEditForm::AddProtelLibObject(AnsiString itemContent)
{
cCurrentMeta = NULL;
TStrings * contentList = String2List(itemContent, " ");
if(contentList->Count < 3)
{
delete contentList;
return;
}
int index = 0;
AnsiString metaName = contentList->Strings[0];
…
if(cCurrentMeta && cCurrentMeta->AllDoneFlag)
{
LibPropertyForm->NewObject(cCurrentMeta); // 加入对象浏览器,显示属性
cObjectList->Add(cCurrentMeta);
CurrentUnit->AddObject(cCurrentMeta);
TPin * pin = dynamic_cast<TPin *>(cCurrentMeta);
if(pin)
{
vector<TPin *> pins;
for(int i = 0; i < cCurrentUnit->MetaNumber; ++i)
{
TPin * p = dynamic_cast<TPin *>(cCurrentUnit->Meta(i));
if(p && p != pin)
pins.push_back(p);
}
bool checkFlag = true;
while(checkFlag)
{
checkFlag = false;
CBW_ITERATOR(vector<TPin *>, pins)
{
bool sameNameFlag = SameText( (*it)->PinName, pin->PinName );
bool sameNumberFlag = SameText( (*it)->PinNumber, pin->PinNumber);
if(sameNameFlag || sameNumberFlag)
checkFlag = true;
if(sameNameFlag)
pin->PinName = pin->PinName + "1";
if(sameNumberFlag)
pin->PinNumber = pin->PinNumber + "1";
}
}
}
}
delete contentList;
}
|
TPin * pin = dynamic_cast<TPin *>(NewMeta(cctPin));
if(contentList->Count == 14)
{
bool dotFlag = contentList->Strings[++index].ToInt();
bool clkFlag = contentList->Strings[++index].ToInt();
int electricalType = contentList->Strings[++index].ToInt();
bool hiddenFlag = contentList->Strings[++index].ToInt();
bool showNameFlag = contentList->Strings[++index].ToInt();
bool showNumberFlag = contentList->Strings[++index].ToInt();
int pinLength = contentList->Strings[++index].ToInt();
int xPos = ProtelGetPos(contentList->Strings[++index], 'x');
int yPos = ProtelGetPos(contentList->Strings[++index], 'y');
int degree = contentList->Strings[++index].ToInt();
int color = contentList->Strings[++index].ToInt();
AnsiString pinName = contentList->Strings[++index];
AnsiString pinNumber = contentList->Strings[++index];
if(electricalType == 1) electricalType = 2;
else if(electricalType == 2) electricalType = 1;
ReplaceStringInStr(pinName, "'", "");
ReplaceStringInStr(pinNumber, "'", "");
ProtelAddPoint(cCurrentMeta, xPos, yPos);
pin->PinLength = pinLength;
pin->PinName = pinName;
pin->PinNumber = pinNumber;
pin->PinDirection = electricalType;
pin->ShowPinName = showNameFlag;
pin->ShowPinNumber = showNumberFlag;
pin->Color = color;
TText * cPinName = dynamic_cast<TText *>(pin->Meta(0));
TText * cPinNumber = dynamic_cast<TText *>(pin->Meta(1));
if(ProtelFontList.size())
{
cPinName->Font = ProtelFontList[ProtelFontList.size() - 1];
cPinNumber->Font = ProtelFontList[ProtelFontList.size() - 1];
}
double dx = pin->PinLine->Points[1].x - (cPinNumber->Left + cPinNumber->Width);
double dy = pin->PinLine->Points[1].y - (cPinNumber->Top + cPinNumber->Height);
if(degree % 4 == 2)
dy = pin->PinLine->Points[1].y - cPinNumber->Top - 2;
cPinNumber->DragBy(dx, dy, true);
dx = pin->PinLine->Points[0].x - (cPinName->Left + cPinName->Width) - 3;
dy = pin->PinLine->Points[0].y - cPinName->CentralPoint.y;
cPinName->DragBy(dx, dy, true);
if(degree)
{
pin->Rotate(degree * 90);
int theta = 0;
if(degree % 2) theta = 90;
cPinName->Theta = theta;
cPinNumber->Theta = theta;
pin->DragBy(xPos - pin->PinLine->Points[0].x, yPos - pin->PinLine->Points[0].y, true);
}
dx = 0; dy = 0;
int delta = 3;
if(degree == 0)
dx = pin->PinLine->Points[0].x - delta - (cPinName->Left + cPinName->Width);
else if(degree == 2)
dx = pin->PinLine->Points[0].x + delta - cPinName->Left;
else if(degree == 1)
dy = pin->PinLine->Points[0].y + delta - cPinName->Top;
else if(degree == 3)
dy = pin->PinLine->Points[0].y - delta - (cPinName->Top + cPinName->Height);
cPinName->DragBy(dx, dy, true);
pin->Visible = !hiddenFlag;
pin->ProtelPinFlag = true;
}
|
TEllipse * ellipse = dynamic_cast<TEllipse *>(NewMeta(cctEllipse));
if(contentList->Count == 10)
{
int xPos = ProtelGetPos(contentList->Strings[++index], 'x');
int yPos = ProtelGetPos(contentList->Strings[++index], 'y');
int xRadius = contentList->Strings[++index].ToInt();
int yRadius = contentList->Strings[++index].ToInt();
int borderWidth = ProtelGetBorderWidth(contentList->Strings[++index]);
int borderColor = contentList->Strings[++index].ToInt();
int fillColor = contentList->Strings[++index].ToInt();
bool drawSolidFlag = contentList->Strings[++index].ToInt();
bool selectionFlag = contentList->Strings[++index].ToInt();
ProtelAddPoint(cCurrentMeta, xPos, yPos, 2);
ellipse->HorzAxis = xRadius;
ellipse->VertAxis = yRadius;
ellipse->LineWidth = borderWidth;
ellipse->LineColor = borderColor;
ellipse->FillColor = fillColor;
ellipse->Transparent = !drawSolidFlag;
cCurrentMeta->DragBy(xPos - cCurrentMeta->CentralPoint.x, yPos - cCurrentMeta->CentralPoint.y, true);
}
|
TArc * arc = dynamic_cast<TArc *>(NewMeta(cctArc));
if(contentList->Count == 10)
{
int xPos = ProtelGetPos(contentList->Strings[++index], 'x');
int yPos = ProtelGetPos(contentList->Strings[++index], 'y');
int xRadius = contentList->Strings[++index].ToInt();
int yRadius = contentList->Strings[++index].ToInt();
int borderWidth = ProtelGetBorderWidth(contentList->Strings[++index]);
double beginTheta = contentList->Strings[++index].ToDouble();
double endTheta = contentList->Strings[++index].ToDouble();
int borderColor = contentList->Strings[++index].ToInt();
bool selectionFlag = contentList->Strings[++index].ToInt();
ProtelAddPoint(cCurrentMeta, xPos, yPos, 4);
arc->HorzAxis = xRadius;
arc->VertAxis = yRadius;
arc->LineWidth = borderWidth;
arc->LineColor = borderColor;
arc->BeginTheta = beginTheta;
arc->EndTheta = endTheta;
cCurrentMeta->DragBy(xPos - cCurrentMeta->CentralPoint.x, yPos - cCurrentMeta->CentralPoint.y, true);
}
|
TText * text = dynamic_cast<TText *>(NewMeta(cctText));
if(contentList->Count == 8)
{
int xPos = ProtelGetPos(contentList->Strings[++index], 'x');
int yPos = ProtelGetPos(contentList->Strings[++index], 'y');
int orientation = contentList->Strings[++index].ToInt();
int color = contentList->Strings[++index].ToInt();
int fontIndex = ProtelGetBorderWidth(contentList->Strings[++index]);
bool selectionFlag = contentList->Strings[++index].ToInt();
AnsiString caption = contentList->Strings[++index];
ReplaceStringInStr(caption, "'", "");
ProtelAddPoint(cCurrentMeta, xPos, yPos);
if(orientation)
text->Theta = orientation * 90;
if(ProtelFontList.size() >= fontIndex)
text->Font = ProtelFontList[fontIndex - 1];
text->SetPenFont("TFont", "Color", color);
text->Caption = caption;
cCurrentMeta->DragBy(
xPos - cCurrentMeta->Left,
yPos - (cCurrentMeta->Top + cCurrentMeta->Height - 5),
true);
cCurrentMeta->Height = text->Font->Size;
}
|
TRectangle * rectangle = dynamic_cast<TRectangle *>(NewMeta(cctRectangle));
if(contentList->Count == 10)
{
int x1Pos = ProtelGetPos(contentList->Strings[++index], 'x');
int y1Pos = ProtelGetPos(contentList->Strings[++index], 'y');
int x2Pos = ProtelGetPos(contentList->Strings[++index], 'x');
int y2Pos = ProtelGetPos(contentList->Strings[++index], 'y');
int borderWidth = ProtelGetBorderWidth(contentList->Strings[++index]);
int borderColor = contentList->Strings[++index].ToInt();
int fillColor = contentList->Strings[++index].ToInt();
bool selectionFlag = contentList->Strings[++index].ToInt();
bool drawSolidFlag = contentList->Strings[++index].ToInt();
ProtelAddPoint(cCurrentMeta, x1Pos, y1Pos);
ProtelAddPoint(cCurrentMeta, x2Pos, y2Pos);
rectangle->LineWidth = borderWidth;
rectangle->LineColor = borderColor;
rectangle->FillColor = fillColor;
rectangle->Transparent = !drawSolidFlag;
}
|
TPolygon * polygon = dynamic_cast<TPolygon *>(NewMeta(cctPolygon));
if(contentList->Count > 6)
{
int borderWidth = ProtelGetBorderWidth(contentList->Strings[++index]);
int borderColor = contentList->Strings[++index].ToInt();
int fillColor = contentList->Strings[++index].ToInt();
bool drawFlag = contentList->Strings[++index].ToInt();
bool selectionFlag = contentList->Strings[++index].ToInt();
int pointNumber = contentList->Strings[++index].ToInt();
for(int i = 0; i < pointNumber; ++i)
{
int xPos = ProtelGetPos(contentList->Strings[++index], 'x');
int yPos = ProtelGetPos(contentList->Strings[++index], 'y');
if(i == (pointNumber - 1))
polygon->AddAllPoint(TFloatPoint(xPos, yPos));
else
ProtelAddPoint(cCurrentMeta, xPos, yPos);
}
polygon->LineWidth = borderWidth;
polygon->LineColor = borderColor;
polygon->FillColor = fillColor;
polygon->Transparent = !drawFlag;
// lineStyle
}
|
TCurve * curve = dynamic_cast<TCurve *>(NewMeta(cctCurve));
if(contentList->Count > 5)
{
int borderWidth = ProtelGetBorderWidth(contentList->Strings[++index]);
int lineStyle = ProtelLineStyle(contentList->Strings[++index]);
int color = contentList->Strings[++index].ToInt();
bool selectionFlag = contentList->Strings[++index].ToInt();
int pointNumber = contentList->Strings[++index].ToInt();
for(int i = 0; i < pointNumber; ++i)
{
int xPos = ProtelGetPos(contentList->Strings[++index], 'x');
int yPos = ProtelGetPos(contentList->Strings[++index], 'y');
if(i == (pointNumber - 1))
curve->AddAllPoint(TFloatPoint(xPos, yPos));
else
ProtelAddPoint(cCurrentMeta, xPos, yPos);
}
curve->LineWidth = borderWidth;
curve->LineColor = color;
// lineStyle
}
|
TLine * line = dynamic_cast<TLine *>(NewMeta(cctLine));
if(contentList->Count == 9)
{
int x1Pos = ProtelGetPos(contentList->Strings[++index], 'x');
int y1Pos = ProtelGetPos(contentList->Strings[++index], 'y');
int x2Pos = ProtelGetPos(contentList->Strings[++index], 'x');
int y2Pos = ProtelGetPos(contentList->Strings[++index], 'y');
int lineWidth = ProtelGetBorderWidth(contentList->Strings[++index]);
int lineStyle = ProtelLineStyle(contentList->Strings[++index]);
int lineColor = contentList->Strings[++index].ToInt();
bool selectionFlag = contentList->Strings[++index].ToInt();
ProtelAddPoint(cCurrentMeta, x1Pos, y1Pos);
ProtelAddPoint(cCurrentMeta, x2Pos, y2Pos);
line->LineWidth = lineWidth;
line->LineColor = lineColor;
// lineStyle
}
|
TArc * arc = dynamic_cast<TArc *>(NewMeta(cctArc));
if(contentList->Count == 9)
{
int xPos = ProtelGetPos(contentList->Strings[++index], 'x');
int yPos = ProtelGetPos(contentList->Strings[++index], 'y');
int xRadius = contentList->Strings[++index].ToInt();
int yRadius = xRadius;
int borderWidth = ProtelGetBorderWidth(contentList->Strings[++index]);
double beginTheta = contentList->Strings[++index].ToDouble();
double endTheta = contentList->Strings[++index].ToDouble();
int borderColor = contentList->Strings[++index].ToInt();
bool selectionFlag = contentList->Strings[++index].ToInt();
ProtelAddPoint(cCurrentMeta, xPos, yPos, 4);
arc->HorzAxis = xRadius;
arc->VertAxis = yRadius;
arc->LineWidth = borderWidth;
arc->LineColor = borderColor;
arc->BeginTheta = beginTheta;
arc->EndTheta = endTheta;
cCurrentMeta->DragBy(xPos - cCurrentMeta->CentralPoint.x, yPos - cCurrentMeta->CentralPoint.y, true);
}
|
TCbwObject * __fastcall TLibEditForm::NewMeta(CbwClassType type)
{
cCurrentMeta = (TCbwObject *)Build[type]();
cCurrentMeta->XMLFile = cXmlFile;
cCurrentMeta->Ratio = Ratio;
cCurrentMeta->Canvas = PaintBox->Canvas;
return cCurrentMeta;
}
void __fastcall ProtelAddPoint(TCbwObject * object, double x, double y, int times = 1)
{
for(int i = 0; i < times; ++i)
object->AddPoint(TFloatPoint(x, y));
}
int __fastcall ProtelGetPos(AnsiString str, char type)
{
int result = str.ToInt();
if(type == 'x' || type == 'X')
result = 400 + result;
if(type == 'y' || type == 'Y')
result = 400 - result;
return result;
}
int __fastcall ProtelGetBorderWidth(AnsiString str)
{
int result = str.ToInt();
return result;
}
int __fastcall ProtelLineStyle(AnsiString str)
{
int result = str.ToInt();
return result;
}
|