919 lines
32 KiB
C++
919 lines
32 KiB
C++
#include "vectorfont.h"
|
||
#include <QFile>
|
||
#include <qmath.h>
|
||
#include "main.h"
|
||
|
||
VectorFont::VectorFont(QObject *parent) :
|
||
QObject(parent)
|
||
{
|
||
m_iDPMM = 40;
|
||
m_pChinese_char = NULL;
|
||
m_pEnglish_char = NULL;
|
||
m_nChinese_char_count = 0;
|
||
m_nEnglish_char_count = 0;
|
||
IniVectorFont();
|
||
}
|
||
|
||
VectorFont::~VectorFont()
|
||
{
|
||
if(m_pChinese_char != NULL)
|
||
{
|
||
delete []m_pChinese_char;
|
||
m_pChinese_char = NULL;
|
||
}
|
||
if(m_pEnglish_char != NULL)
|
||
{
|
||
delete []m_pEnglish_char;
|
||
m_pEnglish_char = NULL;
|
||
}
|
||
}
|
||
|
||
void VectorFont::IniVectorFont()
|
||
{
|
||
QFile fntFile;
|
||
QString strCharFileName;
|
||
|
||
BYTE byte[10];
|
||
int nCharCount_C;
|
||
int nCharCount_E;
|
||
CChinese_char Chinese_char1;
|
||
CEnglish_char English_char1;
|
||
int nCountChar;
|
||
|
||
|
||
QString appPath = QCoreApplication::applicationDirPath();
|
||
QChar separator = QChar('/');
|
||
if(!appPath.contains(separator)) // 判断分隔符
|
||
{
|
||
separator = QChar('\\');
|
||
}
|
||
m_workPath = appPath + separator;
|
||
|
||
|
||
strCharFileName = m_workPath + "english.fnt";
|
||
//qDebug()<< "strCharFileName" << strCharFileName;
|
||
fntFile.setFileName(strCharFileName);
|
||
|
||
if(!fntFile.open(QIODevice::ReadOnly))
|
||
{
|
||
qDebug() <<"english file open failed";
|
||
return;
|
||
}
|
||
|
||
fntFile.seek(0);
|
||
fntFile.read((char*)byte,10);
|
||
|
||
m_nInternalLeading_E=(int)((WORD)byte[0] | ((WORD)byte[1] << 8));
|
||
m_nHeight_E=(int)((WORD)byte[2] | ((WORD)byte[3] << 8));
|
||
m_nDescent_E=(int)((WORD)byte[4] | ((WORD)byte[5] << 8));
|
||
nCharCount_E=(int)((DWORD)byte[6] | ((DWORD)byte[7] << 8) | ((DWORD)byte[9] << 16) | ((DWORD)byte[9] << 24));
|
||
//m_aEnglish_char.clear();
|
||
m_pEnglish_char = new CEnglish_char[nCharCount_E];
|
||
m_nEnglish_char_count = nCharCount_E;
|
||
fntFile.seek(10);
|
||
|
||
nCountChar=nCharCount_E;
|
||
while (nCountChar > 0)
|
||
{
|
||
fntFile.read((char*)byte,10);
|
||
|
||
English_char1.m_wCharCode=(WORD)byte[0] | ((WORD)byte[1] << 8);
|
||
English_char1.m_wBytes=(WORD)byte[2] | ((WORD)byte[3] << 8);
|
||
English_char1.m_wWidth=(WORD)byte[4] | ((WORD)byte[5] << 8);
|
||
English_char1.m_dwPosition=(DWORD)byte[6] | ((DWORD)byte[7] << 8) | ((DWORD)byte[9] << 16) | ((DWORD)byte[9] << 24);
|
||
|
||
m_pEnglish_char[nCharCount_E-nCountChar] = English_char1;
|
||
//m_aEnglish_char.append(English_char1);
|
||
|
||
nCountChar--;
|
||
}
|
||
fntFile.close();
|
||
|
||
strCharFileName = m_workPath + "Hz.fnt";
|
||
//qDebug()<< "strCharFileName" << strCharFileName;
|
||
fntFile.setFileName(strCharFileName);
|
||
if(!fntFile.open(QIODevice::ReadOnly))
|
||
{
|
||
qDebug() <<"chinese file open failed";
|
||
return;
|
||
}
|
||
fntFile.seek(0);
|
||
fntFile.read((char*)byte,8);
|
||
|
||
m_nWidth_C=(int)((WORD)byte[0] | ((WORD)byte[1] << 8));
|
||
m_nHeight_C=(int)((WORD)byte[2] | ((WORD)byte[3] << 8));
|
||
nCharCount_C=(int)((DWORD)byte[4] | ((DWORD)byte[5] << 8) | ((DWORD)byte[6] << 16) | ((DWORD)byte[7] << 24));
|
||
|
||
//m_aChinese_char.clear();
|
||
m_pChinese_char = new CChinese_char[nCharCount_C];
|
||
m_nChinese_char_count = nCharCount_C;
|
||
|
||
fntFile.seek(8);
|
||
nCountChar=nCharCount_C;
|
||
while (nCountChar > 0)
|
||
{
|
||
fntFile.read((char*)byte,8);
|
||
|
||
Chinese_char1.m_wCharCode=(WORD)byte[0] | ((WORD)byte[1] << 8);
|
||
Chinese_char1.m_wBytes=(WORD)byte[2] | ((WORD)byte[3] << 8);
|
||
Chinese_char1.m_dwPosition=(DWORD)byte[4] | ((DWORD)byte[5] << 8) | ((DWORD)byte[6] << 16) | ((DWORD)byte[7] << 24);
|
||
|
||
|
||
m_pChinese_char[nCharCount_C-nCountChar] = Chinese_char1;
|
||
//m_aChinese_char.append(Chinese_char1);
|
||
nCountChar--;
|
||
}
|
||
fntFile.close();
|
||
|
||
m_dFontAngle = 0;
|
||
m_dFontHeight = 0.375 * 10 * m_iDPMM;
|
||
}
|
||
|
||
|
||
//输入参数:
|
||
// ptPointLU 显示字符串的左上角坐标(即TextOut(...)的x,y值)
|
||
// pbyData 字符的描述数据
|
||
// wBytes 字符的描述数据个数
|
||
// nLeft,nDown 字符的左下角坐标(即以英汉字库的公共单位及坐标水平绘制字符串时,字符的的左下角坐标)
|
||
// nFontScale 字库的长度比例
|
||
void VectorFont::PlotChar(QPoint ptPointLU,BYTE *pbyData,WORD wBytes,int nLeft,int nDown,int nFontScale)
|
||
{
|
||
BYTE byByteX,byByteY;
|
||
QPoint ptCurrentPos,ptCenter,ptPointS,ptPointE;
|
||
QPoint ptPoint1;
|
||
WORD wIndex1;
|
||
WORD wDirection,wLength;
|
||
BOOL bPenUp,bVerTextCommand,bClockwise;
|
||
WORD wRadius,wArcS,wSpan;
|
||
int nRadius;
|
||
double dAngleS,dAngleE,dAngleOffsetS,dAngleOffsetE;
|
||
double dx1,dy1,dx2,dy2,dxc,dyc,dr,dD,dH,dBulge;
|
||
double dCos,dSin;
|
||
double dLToDScale;
|
||
int nHeight;
|
||
|
||
if (wBytes == 0) return;
|
||
|
||
nHeight=(m_nInternalLeading_E + m_nHeight_E) * m_nHeight_E;
|
||
//nHeight=(m_nInternalLeading_E + m_nHeight_E) * m_nHeight_C; //之前
|
||
dLToDScale=(double)nHeight / m_dFontHeight;
|
||
|
||
m_dRake = m_dFontAngle/180.0*PI;
|
||
dCos=cos(m_dRake);
|
||
dSin=sin(m_dRake);
|
||
|
||
ptCurrentPos=QPoint(nLeft,nDown);
|
||
ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
MoveTo(ptPoint1);
|
||
bVerTextCommand=false;
|
||
bPenUp=false;
|
||
wIndex1=0;
|
||
while (wIndex1 < wBytes) {
|
||
switch (pbyData[wIndex1]) {
|
||
case 0x0:
|
||
wIndex1++;
|
||
break;
|
||
case 0x1:
|
||
wIndex1++;
|
||
bPenUp=false;
|
||
break;
|
||
case 0x2:
|
||
wIndex1++;
|
||
bPenUp=true;
|
||
break;
|
||
case 0x3:
|
||
wIndex1++;
|
||
wIndex1++;
|
||
bVerTextCommand=false;
|
||
break;
|
||
case 0x4:
|
||
wIndex1++;
|
||
wIndex1++;
|
||
bVerTextCommand=false;
|
||
break;
|
||
case 0x5:
|
||
wIndex1++;
|
||
bPenUp=true;
|
||
break;
|
||
case 0x6:
|
||
wIndex1++;
|
||
bPenUp=true;
|
||
break;
|
||
case 0x7:
|
||
wIndex1++;
|
||
wIndex1++;
|
||
bPenUp=true;
|
||
break;
|
||
case 0x8:
|
||
if (bVerTextCommand) {
|
||
wIndex1=wIndex1+3;
|
||
}
|
||
else {
|
||
wIndex1++;
|
||
ptCurrentPos.setX(ptCurrentPos.x() + (char)pbyData[wIndex1] * nFontScale);
|
||
wIndex1++;
|
||
ptCurrentPos.setY(ptCurrentPos.y() + (char)pbyData[wIndex1] * nFontScale);
|
||
|
||
ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
if (bPenUp)
|
||
MoveTo(ptPoint1);
|
||
else
|
||
LineTo(ptPoint1);
|
||
|
||
wIndex1++;
|
||
}
|
||
bVerTextCommand=false;
|
||
break;
|
||
case 0x9:
|
||
if (bVerTextCommand) {
|
||
wIndex1++;
|
||
byByteX=pbyData[wIndex1];
|
||
wIndex1++;
|
||
byByteY=pbyData[wIndex1];
|
||
while ((byByteX != 0) || (byByteY != 0)) {
|
||
wIndex1++;
|
||
byByteX=pbyData[wIndex1];
|
||
wIndex1++;
|
||
byByteY=pbyData[wIndex1];
|
||
}
|
||
wIndex1++;
|
||
}
|
||
else {
|
||
wIndex1++;
|
||
byByteX=pbyData[wIndex1];
|
||
wIndex1++;
|
||
byByteY=pbyData[wIndex1];
|
||
while ((byByteX != 0) || (byByteY != 0)) {
|
||
ptCurrentPos.setX(ptCurrentPos.x() + (char)byByteX * nFontScale);
|
||
ptCurrentPos.setY(ptCurrentPos.y() + (char)byByteY * nFontScale);
|
||
|
||
ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
if (bPenUp)
|
||
MoveTo(ptPoint1);
|
||
else
|
||
LineTo(ptPoint1);
|
||
|
||
wIndex1++;
|
||
byByteX=pbyData[wIndex1];
|
||
wIndex1++;
|
||
byByteY=pbyData[wIndex1];
|
||
}
|
||
|
||
wIndex1++;
|
||
}
|
||
bVerTextCommand=false;
|
||
break;
|
||
case 0xA:
|
||
if (bVerTextCommand) {
|
||
wIndex1=wIndex1+3;
|
||
}
|
||
else {
|
||
wIndex1++;
|
||
wRadius=(WORD)pbyData[wIndex1];
|
||
wIndex1++;
|
||
if (((char)pbyData[wIndex1]) < 0) bClockwise=true;
|
||
else bClockwise=false;
|
||
wArcS=(WORD)pbyData[wIndex1];
|
||
wArcS=wArcS & 0x70;
|
||
wArcS=wArcS >> 4;
|
||
wSpan=(WORD)pbyData[wIndex1];
|
||
wSpan=wSpan & 0x7;
|
||
|
||
//计算圆心
|
||
ptCenter=ptCurrentPos;
|
||
ptCenter.setX(ptCenter.x() - ((double)wRadius * (double)nFontScale * cos((double)wArcS * 45.0 / 180.0 * 3.14159265359))+0.5);
|
||
ptCenter.setY(ptCenter.y() - ((double)wRadius * (double)nFontScale * sin((double)wArcS * 45.0 / 180.0 * 3.14159265359))+0.5);
|
||
|
||
dAngleS=(double)wArcS * 45.0 / 180.0 * 3.14159265359;
|
||
if (bClockwise) dAngleE=dAngleS - (double)wSpan * 45.0 / 180.0 * 3.14159265359;
|
||
else dAngleE=dAngleS + (double)wSpan * 45.0 / 180.0 * 3.14159265359;
|
||
|
||
if (bClockwise) {
|
||
ptPointS.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleE)+0.5);
|
||
ptPointS.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleE)+0.5);
|
||
ptPointE.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleS)+0.5);
|
||
ptPointE.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleS)+0.5);
|
||
ptCurrentPos=ptPointS;
|
||
}
|
||
else {
|
||
ptPointS.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleS)+0.5);
|
||
ptPointS.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleS)+0.5);
|
||
ptPointE.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleE)+0.5);
|
||
ptPointE.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleE)+0.5);
|
||
ptCurrentPos=ptPointE;
|
||
}
|
||
|
||
ptCenter=CPToLP(ptCenter,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
ptPointS=CPToLP(ptPointS,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
ptPointE=CPToLP(ptPointE,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
nRadius=(double)wRadius * (double)nFontScale / dLToDScale + 0.5;
|
||
Arc(ptCenter.x() - nRadius,ptCenter.y() - nRadius,
|
||
ptCenter.x() + nRadius,ptCenter.y() + nRadius,
|
||
ptPointS.x(),ptPointS.y(),ptPointE.x(),ptPointE.y());
|
||
|
||
ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
MoveTo(ptPoint1);
|
||
|
||
wIndex1++;
|
||
}
|
||
bVerTextCommand=false;
|
||
break;
|
||
case 0xB:
|
||
if (bVerTextCommand) {
|
||
wIndex1=wIndex1+6;
|
||
}
|
||
else {
|
||
wIndex1++;
|
||
dAngleOffsetS=(double)((WORD)pbyData[wIndex1]);
|
||
wIndex1++;
|
||
dAngleOffsetE=(double)((WORD)pbyData[wIndex1]);
|
||
wIndex1++;
|
||
wRadius=(WORD)pbyData[wIndex1];
|
||
wRadius=wRadius << 8;
|
||
wIndex1++;
|
||
wRadius=wRadius | (WORD)pbyData[wIndex1];
|
||
wIndex1++;
|
||
if (((char)pbyData[wIndex1]) < 0) bClockwise=true;
|
||
else bClockwise=false;
|
||
wArcS=(WORD)pbyData[wIndex1];
|
||
wArcS=wArcS & 0x70;
|
||
wArcS=wArcS >> 4;
|
||
wSpan=(WORD)pbyData[wIndex1];
|
||
wSpan=wSpan & 0x7;
|
||
|
||
//计算圆心
|
||
ptCenter=ptCurrentPos;
|
||
ptCenter.setX(ptCenter.x() - (double)wRadius * (double)nFontScale * cos((double)wArcS * 45.0 / 180.0 * 3.14159265359)+0.5);
|
||
ptCenter.setY(ptCenter.y() - (double)wRadius * (double)nFontScale * sin((double)wArcS * 45.0 / 180.0 * 3.14159265359)+0.5);
|
||
|
||
dAngleS=(double)wArcS * 45.0;
|
||
dAngleS=dAngleOffsetS * 45.0 / 256.0 + dAngleS;
|
||
if (bClockwise) dAngleE=-(double)wSpan * 45.0;
|
||
else dAngleE=(double)wSpan * 45.0;
|
||
dAngleE=dAngleOffsetE * 45.0 / 256.0 + dAngleE;
|
||
dAngleE=dAngleOffsetE * 45.0 / 256.0 + dAngleE;
|
||
dAngleS=dAngleS / 180.0 * 3.14159265359;
|
||
dAngleE=dAngleE / 180.0 * 3.14159265359;
|
||
|
||
if (bClockwise) {
|
||
ptPointS.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleE)+0.5);
|
||
ptPointS.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleE)+0.5);
|
||
ptPointE.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleS)+0.5);
|
||
ptPointE.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleS)+0.5);
|
||
ptCurrentPos=ptPointS;
|
||
}
|
||
else {
|
||
ptPointS.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleS)+0.5);
|
||
ptPointS.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleS)+0.5);
|
||
ptPointE.setX(ptCenter.x() + (double)wRadius * (double)nFontScale * cos(dAngleE)+0.5);
|
||
ptPointE.setY(ptCenter.y() + (double)wRadius * (double)nFontScale * sin(dAngleE)+0.5);
|
||
ptCurrentPos=ptPointE;
|
||
}
|
||
|
||
ptCenter=CPToLP(ptCenter,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
ptPointS=CPToLP(ptPointS,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
ptPointE=CPToLP(ptPointE,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
nRadius=(double)wRadius * (double)nFontScale / dLToDScale + 0.5;
|
||
|
||
Arc(ptCenter.x() - nRadius,ptCenter.y() - nRadius,
|
||
ptCenter.x() + nRadius,ptCenter.y() + nRadius,
|
||
ptPointS.x(),ptPointS.y(),ptPointE.x(),ptPointE.y());
|
||
|
||
ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
MoveTo(ptPoint1);
|
||
|
||
wIndex1++;
|
||
}
|
||
bVerTextCommand=false;
|
||
break;
|
||
case 0xC:
|
||
if (bVerTextCommand) {
|
||
wIndex1=wIndex1+4;
|
||
}
|
||
else {
|
||
wIndex1++;
|
||
dx1=(double)((char)pbyData[wIndex1]) * (double)nFontScale;
|
||
wIndex1++;
|
||
dy1=(double)((char)pbyData[wIndex1]) * (double)nFontScale;
|
||
wIndex1++;
|
||
dBulge=(double)((char)pbyData[wIndex1]);
|
||
if (((char)pbyData[wIndex1]) < 0) bClockwise=true;
|
||
else bClockwise=false;
|
||
|
||
dD=sqrt(dx1*dx1 + dy1*dy1);
|
||
dH=fabs(dBulge) * dD / 127.0 / 2.0;
|
||
|
||
if (((char)pbyData[wIndex1]) == 0) {
|
||
ptCurrentPos.setX(ptCurrentPos.x() + (int)dx1);
|
||
ptCurrentPos.setY(ptCurrentPos.y() - (int)dy1);
|
||
ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
|
||
if (bPenUp) MoveTo(ptPoint1);
|
||
else LineTo(ptPoint1);
|
||
}
|
||
else {
|
||
if (bClockwise) {
|
||
dx2=-dy1;
|
||
dy2=dx1;
|
||
}
|
||
else {
|
||
dx2=dy1;
|
||
dy2=-dx1;
|
||
}
|
||
dx2=dx2 / dD * dH + dx1 / 2.0;
|
||
dy2=dy2 / dD * dH + dy1 / 2.0;
|
||
|
||
CircleCR(0.0,0.0,dx2,dy2,dx1,dy1,dxc,dyc,dr);
|
||
ptCenter.setX(ptCurrentPos.x() + dxc + 0.5);
|
||
ptCenter.setY(ptCurrentPos.y() + dyc + 0.5);
|
||
|
||
if (bClockwise)
|
||
{
|
||
ptPointS.setX(ptCurrentPos.x() + dx1 + 0.5);
|
||
ptPointS.setY(ptCurrentPos.y() + dy1 + 0.5 );
|
||
ptPointE=ptCurrentPos;
|
||
ptCurrentPos=ptPointS;
|
||
}
|
||
else
|
||
{
|
||
ptPointS=ptCurrentPos;
|
||
ptPointE.setX(ptCurrentPos.x() + dx1 + 0.5);
|
||
ptPointE.setY(ptCurrentPos.y() + dy1 + 0.5);
|
||
ptCurrentPos=ptPointE;
|
||
}
|
||
|
||
ptCenter=CPToLP(ptCenter,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
ptPointS=CPToLP(ptPointS,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
ptPointE=CPToLP(ptPointE,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
nRadius=dr / dLToDScale + 0.5;
|
||
|
||
Arc(ptCenter.x() - nRadius,ptCenter.y() - nRadius,ptCenter.x() + nRadius,ptCenter.y() + nRadius,
|
||
ptPointS.x(),ptPointS.y(),ptPointE.x(),ptPointE.y());
|
||
|
||
ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
MoveTo(ptPoint1);
|
||
}
|
||
|
||
wIndex1++;
|
||
}
|
||
bVerTextCommand=false;
|
||
break;
|
||
case 0xD:
|
||
if (bVerTextCommand) {
|
||
wIndex1=wIndex1+4;
|
||
}
|
||
else {
|
||
wIndex1++;
|
||
while ((pbyData[wIndex1] != 0) || (pbyData[wIndex1+1] != 0)) {
|
||
dx1=(double)((char)pbyData[wIndex1]) * (double)nFontScale;
|
||
wIndex1++;
|
||
dy1=(double)((char)pbyData[wIndex1]) * (double)nFontScale;
|
||
wIndex1++;
|
||
dBulge=(double)((char)pbyData[wIndex1]);
|
||
if (((char)pbyData[wIndex1]) < 0) bClockwise=true;
|
||
else bClockwise=false;
|
||
|
||
dD=sqrt(dx1*dx1 + dy1*dy1);
|
||
dH=fabs(dBulge) * dD / 127.0 / 2.0;
|
||
|
||
if (((char)pbyData[wIndex1]) == 0) {
|
||
ptCurrentPos.setX(ptCurrentPos.x() + (int)dx1);
|
||
ptCurrentPos.setY(ptCurrentPos.y() - (int)dy1);
|
||
ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
|
||
if (bPenUp)
|
||
MoveTo(ptPoint1);
|
||
else
|
||
LineTo(ptPoint1);
|
||
}
|
||
else {
|
||
if (bClockwise) {
|
||
dx2=-dy1;
|
||
dy2=dx1;
|
||
}
|
||
else {
|
||
dx2=dy1;
|
||
dy2=-dx1;
|
||
}
|
||
dx2=dx2 / dD * dH + dx1 / 2.0;
|
||
dy2=dy2 / dD * dH + dy1 / 2.0;
|
||
|
||
CircleCR(0.0,0.0,dx2,dy2,dx1,dy1,dxc,dyc,dr);
|
||
ptCenter.setX(ptCurrentPos.x() + dxc + 0.5);
|
||
ptCenter.setY(ptCurrentPos.y() + dyc + 0.5);
|
||
|
||
if (bClockwise)
|
||
{
|
||
ptPointS.setX(ptCurrentPos.x() + dx1 + 0.5);
|
||
ptPointS.setY(ptCurrentPos.y() + dy1 + 0.5);
|
||
ptPointE=ptCurrentPos;
|
||
ptCurrentPos=ptPointS;
|
||
}
|
||
else
|
||
{
|
||
ptPointS=ptCurrentPos;
|
||
ptPointE.setX(ptCurrentPos.x() + dx1 + 0.5);
|
||
ptPointE.setY(ptCurrentPos.y() + dy1 + 0.5);
|
||
ptCurrentPos=ptPointE;
|
||
}
|
||
|
||
ptCenter=CPToLP(ptCenter,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
ptPointS=CPToLP(ptPointS,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
ptPointE=CPToLP(ptPointE,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
nRadius=dr / dLToDScale + 0.5;
|
||
|
||
Arc(ptCenter.x() - nRadius,ptCenter.y() - nRadius,ptCenter.x() + nRadius,ptCenter.y() + nRadius,
|
||
ptPointS.x(),ptPointS.y(),ptPointE.x(),ptPointE.y());
|
||
|
||
ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
MoveTo(ptPoint1);
|
||
}
|
||
|
||
wIndex1++;
|
||
}
|
||
}
|
||
bVerTextCommand=false;
|
||
break;
|
||
case 0xE:
|
||
bVerTextCommand=true;
|
||
wIndex1++;
|
||
break;
|
||
default:
|
||
if (bVerTextCommand) {
|
||
wIndex1++;
|
||
}
|
||
else {
|
||
wDirection=(WORD)(pbyData[wIndex1] % 16);
|
||
wLength=(WORD)(pbyData[wIndex1] / 16) * (WORD)nFontScale;
|
||
ptCurrentPos=GetNextCoodinate(wDirection,wLength,ptCurrentPos);
|
||
|
||
ptPoint1=CPToLP(ptCurrentPos,nHeight,ptPointLU,dSin,dCos,dLToDScale);
|
||
if (bPenUp) MoveTo(ptPoint1);
|
||
else LineTo(ptPoint1);
|
||
|
||
wIndex1++;
|
||
}
|
||
bVerTextCommand=false;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
QPoint VectorFont::CPToLP(QPoint ptCP,int nHeight,QPoint ptPointLU,double dSin,double dCos,double dScale)
|
||
{
|
||
double dx,dy;
|
||
QPoint ptPoint1;
|
||
|
||
dx=(double)ptCP.x();
|
||
dy=(double)ptCP.y()-(double)nHeight;
|
||
ptPoint1.setX(ptPointLU.x() + ((dx*dCos - dy*dSin) / dScale + 0.5));
|
||
ptPoint1.setY(ptPointLU.y() + ((dx*dSin + dy*dCos) / dScale + 0.5));
|
||
|
||
return ptPoint1;
|
||
}
|
||
|
||
//抬笔移动到点(x,y)
|
||
void VectorFont::MoveTo(long x, long y)
|
||
{
|
||
if(x == 0){}
|
||
if(y == 0){}
|
||
}
|
||
|
||
//抬笔移动到点ptPoint
|
||
void VectorFont::MoveTo(QPoint ptPoint)
|
||
{
|
||
emit siMoveTo(true,ptPoint);
|
||
}
|
||
|
||
//从当前位置画线到点(x,y)
|
||
void VectorFont::LineTo(long x, long y)
|
||
{
|
||
if(x == 0){}
|
||
if(y == 0){}
|
||
}
|
||
|
||
//从当前位置画线到点ptPoint
|
||
void VectorFont::LineTo(QPoint ptPoint)
|
||
{
|
||
emit siLineTo(false,ptPoint);
|
||
}
|
||
|
||
//从(x,y)点开始写字,nCount为字节数
|
||
void VectorFont::TextOutString(int x, int y, const char* lpszString, int nCount)
|
||
{
|
||
QString strEnglish,strChinese;
|
||
QFile fileEnglish,fileChinese;
|
||
BYTE *pbyData;
|
||
int nLeft;
|
||
BYTE byByte1,byByte2;
|
||
WORD wCharCode;
|
||
int nIndex1,nIndex2,nIndex3,nIndex4;
|
||
bool bEnglishChar;
|
||
|
||
strEnglish = m_workPath + "english.fnt";
|
||
strChinese = m_workPath + "Hz.fnt";
|
||
|
||
fileEnglish.setFileName(strEnglish);
|
||
if(!fileEnglish.open(QIODevice::ReadOnly))
|
||
{
|
||
qDebug() <<"file open failed";
|
||
return;
|
||
}
|
||
|
||
fileChinese.setFileName(strChinese);
|
||
if(!fileChinese.open(QIODevice::ReadOnly))
|
||
{
|
||
qDebug() <<"file open failed";
|
||
return;
|
||
}
|
||
|
||
nLeft=0;
|
||
nIndex1=0;
|
||
while (nIndex1 < nCount)
|
||
{
|
||
pbyData=NULL;
|
||
byByte1=(BYTE)lpszString[nIndex1];
|
||
if ((byByte1 >= 128) && ((nIndex1+1) < nCount))
|
||
{
|
||
bEnglishChar=false;
|
||
|
||
nIndex1++;
|
||
byByte2=(BYTE)lpszString[nIndex1];
|
||
wCharCode=(((WORD)byByte1) << 8) | (WORD)byByte2;
|
||
|
||
nIndex2=0;
|
||
nIndex3=m_nChinese_char_count - 1;
|
||
if (m_pChinese_char[nIndex2].m_wCharCode == wCharCode) nIndex4=nIndex2;
|
||
else if (m_pChinese_char[nIndex3].m_wCharCode == wCharCode) nIndex4=nIndex3;
|
||
else nIndex4=(nIndex2 + nIndex3) / 2;
|
||
while (((nIndex3 - nIndex2) > 1) &&
|
||
(m_pChinese_char[nIndex4].m_wCharCode != wCharCode))
|
||
{
|
||
if (m_pChinese_char[nIndex4].m_wCharCode > wCharCode)
|
||
{
|
||
nIndex3=nIndex4;
|
||
if (nIndex2 > nIndex3) break;
|
||
nIndex4=(nIndex2 + nIndex3) / 2;
|
||
}
|
||
else
|
||
{
|
||
nIndex2=nIndex4;
|
||
if (nIndex2 > nIndex3) break;
|
||
nIndex4=(nIndex2 + nIndex3) / 2;
|
||
}
|
||
}
|
||
|
||
if ((m_pChinese_char[nIndex4].m_wCharCode == wCharCode) &&
|
||
(m_pChinese_char[nIndex4].m_wBytes > 0))
|
||
{
|
||
pbyData=new BYTE[m_pChinese_char[nIndex4].m_wBytes + 1];
|
||
|
||
fileChinese.seek(m_pChinese_char[nIndex4].m_dwPosition);
|
||
fileChinese.read((char*)pbyData,m_pChinese_char[nIndex4].m_wBytes);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
bEnglishChar=true;
|
||
wCharCode=(WORD)byByte1;
|
||
nIndex2=0;
|
||
nIndex3=m_nEnglish_char_count - 1;
|
||
if (m_pEnglish_char[nIndex2].m_wCharCode == wCharCode) nIndex4=nIndex2;
|
||
else if (m_pEnglish_char[nIndex3].m_wCharCode == wCharCode) nIndex4=nIndex3;
|
||
else nIndex4=(nIndex2 + nIndex3) / 2;
|
||
while (((nIndex3 - nIndex2) > 1) &&
|
||
(m_pEnglish_char[nIndex4].m_wCharCode != wCharCode))
|
||
{
|
||
if (m_pEnglish_char[nIndex4].m_wCharCode > wCharCode)
|
||
{
|
||
nIndex3=nIndex4;
|
||
if (nIndex2 > nIndex3) break;
|
||
nIndex4=(nIndex2 + nIndex3) / 2;
|
||
}
|
||
else
|
||
{
|
||
nIndex2=nIndex4;
|
||
if (nIndex2 > nIndex3) break;
|
||
nIndex4=(nIndex2 + nIndex3) / 2;
|
||
}
|
||
}
|
||
|
||
if ((m_pEnglish_char[nIndex4].m_wCharCode == wCharCode) &&
|
||
(m_pEnglish_char[nIndex4].m_wBytes > 0)) {
|
||
pbyData=new BYTE[m_pEnglish_char[nIndex4].m_wBytes + 1];
|
||
|
||
fileEnglish.seek(m_pEnglish_char[nIndex4].m_dwPosition);
|
||
fileEnglish.read((char*)pbyData,m_pEnglish_char[nIndex4].m_wBytes);
|
||
}
|
||
}
|
||
if (pbyData != NULL)
|
||
{
|
||
if (bEnglishChar)
|
||
{
|
||
PlotChar(QPoint(x,y),pbyData,m_pEnglish_char[nIndex4].m_wBytes,nLeft,0,m_nHeight_C);
|
||
}
|
||
else
|
||
{
|
||
PlotChar(QPoint(x,y),pbyData,m_pChinese_char[nIndex4].m_wBytes,nLeft,0,m_nInternalLeading_E + m_nHeight_E);
|
||
}
|
||
delete []pbyData;
|
||
if (bEnglishChar) nLeft=nLeft + m_pEnglish_char[nIndex4].m_wWidth * m_nHeight_C;
|
||
else nLeft=nLeft + m_nWidth_C * (m_nInternalLeading_E + m_nHeight_E);
|
||
}
|
||
else
|
||
{
|
||
if (bEnglishChar) nLeft=nLeft + m_pEnglish_char[0].m_wWidth * m_nHeight_C;
|
||
else nLeft=nLeft + m_nWidth_C * (m_nInternalLeading_E + m_nHeight_E);
|
||
}
|
||
|
||
nIndex1++;
|
||
}
|
||
|
||
fileEnglish.close();
|
||
fileChinese.close();
|
||
}
|
||
//画弧,从Start逆时针画到End
|
||
void VectorFont::Arc(int nLeftRect,int nTopRect,int nRightRect,int nBottomRect,
|
||
int nXStartArc,int nYStartArc,int nXEndArc,int nYEndArc)
|
||
{
|
||
double dXC,dYC,dRadius;
|
||
double dx,dy;
|
||
double dAngleS,dAngleE,dAngle,dStep;
|
||
double dCos,dSin;
|
||
int nCount;
|
||
|
||
dXC=((double)nLeftRect + (double)nRightRect) / 2.0;
|
||
dYC=((double)nTopRect + (double)nBottomRect) / 2.0;
|
||
dRadius=((double)nRightRect - (double)nLeftRect) / 2.0;
|
||
|
||
dAngleS=angle_2(dXC,dYC,(double)nXStartArc,(double)nYStartArc);
|
||
dAngleE=angle_2(dXC,dYC,(double)nXEndArc,(double)nYEndArc);
|
||
while (dAngleE >= dAngleS) dAngleE=dAngleE - 2.0 * PI;
|
||
|
||
if ((nXStartArc == nXEndArc) && (nYStartArc == nYEndArc))
|
||
{
|
||
dAngleS=0.0;
|
||
dAngleE=-2.0 * PI;
|
||
}
|
||
|
||
dSin=qSin(dAngleS);
|
||
dCos=qCos(dAngleS);
|
||
dx=dRadius * dCos + dXC;
|
||
dy=dRadius * dSin + dYC;
|
||
MoveTo(dx+0.5,dy+0.5);
|
||
|
||
nCount=120;
|
||
dStep=PI / 180.0 * (360.0 / (double)nCount); //3度
|
||
dAngle=dAngleS;
|
||
while (dAngle > dAngleE)
|
||
{
|
||
dAngle=dAngle - dStep;
|
||
if (dAngle < dAngleE) dAngle=dAngleE;
|
||
dSin=qSin(dAngle);
|
||
dCos=qCos(dAngle);
|
||
dx=dRadius * dCos + dXC;
|
||
dy=dRadius * dSin + dYC;
|
||
LineTo(dx+0.5,dy+0.5);
|
||
}
|
||
|
||
}
|
||
|
||
QPoint VectorFont::GetNextCoodinate(WORD wDirection,WORD wLength,QPoint ptPoint)
|
||
{
|
||
QPoint ptPoint1;
|
||
|
||
switch (wDirection) {
|
||
case 0:
|
||
ptPoint1.setX( ptPoint.x() + (int)wLength);
|
||
ptPoint1.setY(ptPoint.y());
|
||
break;
|
||
case 1:
|
||
ptPoint1.setX(ptPoint.x() + (int)wLength);
|
||
ptPoint1.setY(ptPoint.y() + (int)wLength/2);
|
||
break;
|
||
case 2:
|
||
ptPoint1.setX(ptPoint.x() + (int)wLength);
|
||
ptPoint1.setY(ptPoint.y() + (int)wLength);
|
||
break;
|
||
case 3:
|
||
ptPoint1.setX(ptPoint.x() + (int)wLength/2);
|
||
ptPoint1.setY(ptPoint.y() + (int)wLength);
|
||
break;
|
||
case 4:
|
||
ptPoint1.setX(ptPoint.x());
|
||
ptPoint1.setY(ptPoint.y() + (int)wLength);
|
||
break;
|
||
case 5:
|
||
ptPoint1.setX(ptPoint.x() - (int)wLength/2);
|
||
ptPoint1.setY(ptPoint.y() + (int)wLength);
|
||
break;
|
||
case 6:
|
||
ptPoint1.setX(ptPoint.x() - (int)wLength);
|
||
ptPoint1.setY(ptPoint.y() + (int)wLength);
|
||
break;
|
||
case 7:
|
||
ptPoint1.setX(ptPoint.x() - (int)wLength);
|
||
ptPoint1.setY(ptPoint.y() + (int)wLength/2);
|
||
break;
|
||
case 8:
|
||
ptPoint1.setX(ptPoint.x() - (int)wLength);
|
||
ptPoint1.setY(ptPoint.y());
|
||
break;
|
||
case 9:
|
||
ptPoint1.setX(ptPoint.x() - (int)wLength);
|
||
ptPoint1.setY(ptPoint.y() - (int)wLength/2);
|
||
break;
|
||
case 10:
|
||
ptPoint1.setX(ptPoint.x() - (int)wLength);
|
||
ptPoint1.setY(ptPoint.y() - (int)wLength);
|
||
break;
|
||
case 11:
|
||
ptPoint1.setX(ptPoint.x() - (int)wLength/2);
|
||
ptPoint1.setY(ptPoint.y() - (int)wLength);
|
||
break;
|
||
case 12:
|
||
ptPoint1.setX(ptPoint.x());
|
||
ptPoint1.setY(ptPoint.y() - (int)wLength);
|
||
break;
|
||
case 13:
|
||
ptPoint1.setX(ptPoint.x() + (int)wLength/2);
|
||
ptPoint1.setY(ptPoint.y() - (int)wLength);
|
||
break;
|
||
case 14:
|
||
ptPoint1.setX(ptPoint.x() + (int)wLength);
|
||
ptPoint1.setY(ptPoint.y() - (int)wLength);
|
||
break;
|
||
case 15:
|
||
ptPoint1.setX(ptPoint.x() + (int)wLength);
|
||
ptPoint1.setY(ptPoint.y() - (int)wLength/2);
|
||
break;
|
||
}
|
||
|
||
return ptPoint1;
|
||
}
|
||
|
||
//求两点确定的直线与X轴的夹角,在[0,2pi)之间
|
||
//输入参数:
|
||
// (startx,starty) 起点
|
||
// (endx,endy) 终点
|
||
//返回值:
|
||
// 夹角
|
||
double VectorFont::angle_2(int startx,int starty,int endx,int endy)
|
||
{
|
||
//直线与X轴之间的夹角 X轴向量OE(1,0)
|
||
double dAngle = 0;
|
||
if((endx == startx) && (endy == starty))
|
||
{
|
||
return dAngle;
|
||
}
|
||
//求直线的向量坐标
|
||
double dX = endx - startx;
|
||
double dY = endy - starty;
|
||
dAngle = qAcos((dX)/(qSqrt(dX*dX + dY*dY)));
|
||
return dAngle;
|
||
}
|
||
|
||
///////////////////////// 计算三点定圆时的圆心和半径 ///////////////////////////
|
||
// 输入参数:三个样点(x1,y1),(x2,y2),(x3,y3)
|
||
// 算法描述:
|
||
// 过(x1,y1),(x2,y2)的中点作垂线L1,
|
||
// 过(x2,y2),(x3,y3)的中点作垂线L2,
|
||
// 求L1,L2的交点.
|
||
// 输出参数:
|
||
// 如果不能形成圆返回false,
|
||
// 否则返回true其中圆心为(cx,cy),半径=cr.
|
||
// 按逆时针方向画弧时,如cr>0 则(x1,y1)是起点,(x3,y3)是终点,
|
||
// 如cr<0 则(x3,y3)是起点,(x1,y1)是终点.
|
||
// 特别说明:此处所说的逆时针是指显示器而言,如果对于对X向右为正,
|
||
// Y向上为正的坐标系来说此处是顺时针
|
||
//bool CircleCR(int x1,int y1,int x2,int y2,int x3,int y3,int& cx,int& cy,int& cr);
|
||
////////////////////////////////////////////////////////////////////////////////
|
||
bool VectorFont::CircleCR(double x1,double y1,double x2,double y2,double x3,double y3,double& cx,double& cy,double& cr)
|
||
{
|
||
double a1,b1,c1,a2,b2,c2;
|
||
if(((x1 ==x2) && (y1==y2)) || ((x1 ==x3) && (y1==y3)) || ((x2 ==x3) && (y2==y3)))
|
||
{
|
||
return false;
|
||
}
|
||
a1 = x1 - x2;
|
||
b1 = y1 - y2;
|
||
c1 = -a1 * (x1 + x2) / 2.0 - b1 * (y1 + y2)/2.0;
|
||
a2 = x3 - x2;
|
||
b2 = y3 - y2;
|
||
c2 = -a2 * (x2 + x3) / 2.0 - b2 * (y2 + y3)/2.0;
|
||
|
||
double D = a1*b2 - a2*b1;
|
||
if(D == 0)//两直线平行
|
||
{
|
||
return false;
|
||
}
|
||
|
||
cx = (b1*c2 - b2*c1)/D;
|
||
cy = (c1*a2 - c2*a1)/D;
|
||
|
||
//用圆心和其中一个点求距离得到半径:
|
||
cr = qSqrt((cx - x1)*(cx - x1) + (cy - y1)*(cy - y1));
|
||
return true;
|
||
}
|
||
|