#include "..\..\..\..\Library\Windows\VL_WinMain.h"
 #include "..\..\..\..\Library\Windows\VL_WinGDI.h"
 
 using namespace vl;
 using namespace vl::windows;
 
 class MyForm : public VL_WinForm
 {
 protected:
     VL_WinDIB* FBuffer;
     VL_WinDC* FFormDC;
     VL_WinDC* FBufferDC;
 
     FIXED dtof(VDouble D)
     {
         VInt l;
         l=(VInt)(D * 65536L);
         return *(FIXED *)&l;
     }
 
     VDouble ftod(FIXED F)
     {
         return F.value+(VDouble)F.fract/65536;
     }
 
     POINT GetPoint(POINTFX fx , GLYPHMETRICS& gm , TEXTMETRIC& TextMetric , POINT Origin)
     {
         /*Y值比最高点搞出了Ascent,即Top与Baseline的距离*/
         POINT Result;
         Result.x=(VInt)ftod(fx.x)+Origin.x;
         Result.y=(VInt)ftod(fx.y)+Origin.y+TextMetric.tmAscent;
         return Result;
     }
 
     void DrawCurve(VBuffer Buffer , VInt Count , GLYPHMETRICS gm , POINT Origin)
     {
         VL_WinPen::Ptr Pen_Line=new VL_WinPen(PS_SOLID,1,RGB(255,0,0));
         VL_WinPen::Ptr Pen_Bezier=new VL_WinPen(PS_SOLID,1,RGB(0,0,255));
         VL_WinPen::Ptr Pen_Close=new VL_WinPen(PS_SOLID,1,RGB(0,0,0));
 
         TEXTMETRIC TextMetric;
         GetTextMetrics(FBufferDC->GetHandle(),&TextMetric);
 
         while(Count>0)
         {
             TTPOLYGONHEADER* Header=(TTPOLYGONHEADER*)Buffer;
             VInt Remain=Header->cb-sizeof(TTPOLYGONHEADER);
             VBuffer Start=Buffer+sizeof(TTPOLYGONHEADER);
             POINTFX StartPoint=Header->pfxStart;
             POINTFX InitPoint=StartPoint;
             while(Remain>0)
             {
                 TTPOLYCURVE* Curve=(TTPOLYCURVE*)Start;
                 switch(Curve->wType)
                 {
                 case TT_PRIM_LINE:
                     {
                         POINT* Points=new POINT[Curve->cpfx+1];
                         Points[0]=GetPoint(StartPoint,gm,TextMetric,Origin);
                         for(VInt i=0;i<Curve->cpfx;i++)
                         {
                             Points[i+1]=GetPoint(Curve->apfx[i],gm,TextMetric,Origin);
                         }
                         /*红*/
                         FBufferDC->SetPen(Pen_Line);
                         FBufferDC->PolyLine(Points,Curve->cpfx+1);
                         delete[] Points;
                     }
                     break;
                 case TT_PRIM_QSPLINE:
                     {
                         /*
                         Quadratic Bezier转Cubic Bezier
                         假设一共有n个点,从1开始,那么在2-3,3-4,,(n-2)-(n-1)中间插入中点
                         遍历每三个点(1,2,3) (3,4,5)  ((n-2),(n-1),n),
                             将A,B,C变成A,2(A+B)/3,(B+C)/3,C
                         这个时候得到一个完整的点数组,直接PolyBezier
                         */
                         VInt PointCount=1+(Curve->cpfx-1)*3;
                         POINT* Points=new POINT[PointCount];
                         POINT P0=GetPoint(StartPoint,gm,TextMetric,Origin);
                         POINT P1,P2;
                         Points[0]=P0;
                         VInt Current=1;
 
                         for(VInt i=0;i<Curve->cpfx;)
                         {
                             P1=GetPoint(Curve->apfx[i++],gm,TextMetric,Origin);
                             if(i==Curve->cpfx-1)
                             {
                                 P2=GetPoint(Curve->apfx[i++],gm,TextMetric,Origin);
                             }
                             else
                             {
                                 P2=GetPoint(Curve->apfx[i],gm,TextMetric,Origin);
                                 P2.x=(P1.x+P2.x)/2;
                                 P2.y=(P1.y+P2.y)/2;
                             }
 
                             Points[Current+0].x=P0.x + 2*(P1.x - P0.x)/3;
                             Points[Current+0].y=P0.y + 2*(P1.y - P0.y)/3;
                             Points[Current+1].x = P1.x + 1*(P2.x - P1.x)/3;
                             Points[Current+1].y = P1.y + 1*(P2.y - P1.y)/3;
                             Points[Current+2]=P2;
                             Current+=3;
                             P0=P2;
                         }
                         /*蓝*/
                         FBufferDC->SetPen(Pen_Bezier);
                         FBufferDC->PolyBezier(Points,PointCount);
                         delete[] Points;
                     }
                     break;
                 case TT_PRIM_CSPLINE:
                     {
                         POINT* Points=new POINT[Curve->cpfx+1];
                         Points[0]=GetPoint(StartPoint,gm,TextMetric,Origin);
                         for(VInt i=0;i<Curve->cpfx;i++)
                         {
                             Points[i+1]=GetPoint(Curve->apfx[i],gm,TextMetric,Origin);
                         }
                         /*蓝*/
                         FBufferDC->SetPen(Pen_Bezier);
                         FBufferDC->PolyLine(Points,Curve->cpfx+1);
                         delete[] Points;
                     }
                     break;
                 }
                 StartPoint=Curve->apfx[Curve->cpfx-1];
                 Start+=sizeof(TTPOLYCURVE)+(Curve->cpfx-1)*sizeof(POINTFX);
                 Remain-=sizeof(TTPOLYCURVE)+(Curve->cpfx-1)*sizeof(POINTFX);
             }
             if(
                 (StartPoint.x.value!=InitPoint.x.value)||
                 (StartPoint.x.fract!=InitPoint.x.fract)||
                 (StartPoint.y.value!=InitPoint.y.value)||
                 (StartPoint.y.fract!=InitPoint.y.fract)
                 )
             {
                 POINT P1=GetPoint(StartPoint,gm,TextMetric,Origin);
                 POINT P2=GetPoint(InitPoint,gm,TextMetric,Origin);
                 FBufferDC->SetPen(Pen_Close);
                 FBufferDC->MoveTo(P1.x,P1.y);
                 FBufferDC->LineTo(P2.x,P2.y);
             }
             InitPoint=StartPoint;
             Buffer+=Header->cb;
             Count-=Header->cb;
         }
     }
 
     void DrawString(VInt X , VInt Y , PWChar String , VBool GDIFirst)
     {
         if(GDIFirst)
         {
             FBufferDC->SetTextColor(RGB(255,255,0));
             FBufferDC->DrawString(X,Y,String);
         }
         {
             GLYPHMETRICS gm;
             /*初始化变换矩阵:上下倒转*/
             MAT2 mat;
             mat.eM11=dtof(1);
             mat.eM12=dtof(0);
             mat.eM21=dtof(0);
             mat.eM22=dtof(-1);
             POINT Origin={X,Y};
             for(VInt i=0;String[i];i++)
             {
                 DWORD BufferLength=GetGlyphOutline(FBufferDC->GetHandle(),String[i],GGO_NATIVE,&gm,0,0,&mat);
                 if(BufferLength!=GDI_ERROR)
                 {
                     VBuffer Buffer=new VByte[BufferLength];
                     DWORD Result=GetGlyphOutline(FBufferDC->GetHandle(),String[i] ,GGO_NATIVE,&gm,BufferLength,Buffer,&mat);
                     DrawCurve(Buffer,BufferLength,gm,Origin);
                     Origin.x+=gm.gmCellIncX;
                     Origin.y+=gm.gmCellIncY;
                     delete[] Buffer;
                 }
             }
         }
         if(!GDIFirst)
         {
             FBufferDC->SetTextColor(RGB(255,255,0));
             FBufferDC->DrawString(X,Y,String);
         }
     }
 public:
 
     MyForm():VL_WinForm(true)
     {
         FBuffer=new VL_WinDIB(800,600);
         FBufferDC=&FBuffer->DC;
         FBufferDC->FillRect(0,0,800,600);
         FBufferDC->SetFont(new VL_WinFont(L"宋体",200,0,0,0,400,false,false,false,false));
         FBufferDC->SetBackTransparent(true);
         FFormDC=new VL_WinControlDC(GetHandle());
 
         PWChar String=L"汉字ABC";
         DrawString(50,50,String,true);
         DrawString(50,350,String,false);
 
         SetMaximizeBox(false);
         SetMinimizeBox(false);
         SetBorder(vwfbSingle);
         SetClientWidth(800);
         SetClientHeight(600);
         SetText(L"Text Outline");
         MoveCenter();
 
         OnPaint.Bind(this,&MyForm::Form_OnPaint);
 
         Show();
     }
 
     ~MyForm()
     {
         delete FFormDC;
         delete FBuffer;
     }
 
     void Form_OnPaint(VL_Base* Sender)
     {
         FFormDC->Draw(0,0,FBuffer);
     }
 };
 
 void main()
 {
     new MyForm();
     GetApplication()->Run();
 }Visual C++Java