#include "vectorfont.h" #include #include #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; }