트루타입 글리프를 윤곽선 그리기 방법

기술 자료 번역 기술 자료 번역
기술 자료: 243285 - 이 문서가 적용되는 제품 보기.
모두 확대 | 모두 축소

요약

Win32 API GetGlyphOutline 함수를 TrueType 글꼴을 기본 문자 모양 개요 데이터를 반환할 수 있습니다. 트루타입 문자 모양 개요 그리려면 일련의 베지어 줄 정의 네이티브 B-스플라인 정의에서 데이터는 변환해야 합니다. 다음 PolyBezier Win32 API 함수를 윤곽선을 그리는 데 사용할 수 있습니다.

추가 정보

Win32 응용 프로그래밍 Interface(API) GetGlyphOutline 함수에서 트루타입 개요를 검색할 수 있습니다. GGO_NATIVE 형식 옵션이 트루타입 개요 정방형 B-스플라인 곡선 사용하여 버퍼를 채웁니다. 정방형 B-스플라인에 의해 트루타입 트루타입 글꼴 파일의 문자 모양 개요 설명하는 데 사용됩니다. 이러한 개요 곡선을 그리려면 하나가 B-스플라인 그리기 기능을 구현하는 지정하거나 Win32 API PolyBezier 함수에서 사용할 수 있습니다.

정방형 B-스플라인 곡선 클래스의 몇 가지 제어 지점을 통해 여러 곡선 세그먼트의 경로를 정의하는 매개 변수 곡선 있습니다. 두 번째 매개 변수 순서를 곡선을 정방형 곡선입니다. 정방형 스플라인 직접 그릴 수 있는 API 함수가 있지만 해당 Quadratic 그릴 수 Cubic Win32 API를 사용하여 변환할 경우 3차원 곡선을 그리는 데 함수, PolyBezier 합니다.

일반적으로 특정 및 매개 변수 곡선 정방형 B-스플라인 곡선 컴퓨터 과학 그래픽 well-researched 항목이 있습니다. 매우 복잡할 수도 있습니다. 다양한 텍스트를 알고리즘을 게시한 정방형 스플라인 그리기 함수를 구현하는 데 사용할 수 있지만 이러한 알고리즘을 설명하는 이 문서에서는 다루지 않습니다.

3차원 곡선 순서 입방형 또는 세 번째 매개 변수 곡선을 때문에 PolyBezier 함수를 정방형 스플라인 그릴 수 있습니다. 두 번째 순서를 수식 정방형 스플라인 있기 때문에 높은 순서 입방형 수식 측면에서 표현할 수 있습니다. 해당 파생 quadratic, cubic 같이 나타내기 위한 수식 예제 코드에서 주어진 있지만 이 문서에서 설명하는 것입니다.

이 문서의 예제 코드에서는 GetGlyphOutline 함수에서 반환된 GGO_NATIVE 상형 문자 버퍼를 구문 분석하는 방법을 데모를 것입니다. GGO_NATIVE 형식 플래그에 의해 반환된 버퍼 TTPOLYGONHEADER 구조를 따릅니다. TTPOLYGONHEADER 구조와 바로 뒤에 데이터를 트루타입 문자 한 배분 형식을 구성합니다. 배분 형식을 이렇게 명시적으로 반환된 경우 암시적으로 닫혀 있는 한 전체 곡선을 경로입니다.

TTPOLYGONHEADERTTPOLYCURVE 구조의 설명서 플랫폼 SDK를 참조하십시오.

문자 모양 배분 형식을 나타내는 TTPOLYCURVE 구조체에서 곡선 세그먼트가 여러 개 구성됩니다. 배분 형식에서 TTPOLYGONHEADERTTPOLYCURVE 구조 및 좌표 지점 데이터를 하나 이상의 옵니다. pfxStart 구성원, 배분 형식 좌표 시작점을 제공합니다. TTPOLYGONHEADER 따라 곡선 레코드 개수는 cb 구성원에 의해 지정됩니다. 문자 모양 원점을 기준으로 출발점입니다. 문자 모양의 원점을 문자에서 문자 기준선의 왼쪽된 아래 모서리에 있습니다.

TTPOLYCURVE 곡선의 레코드마다 곡선 세그먼트를 정방형 B-스플라인 컨트롤 포인트 또는 간단한 폴리라인 지점 중 구성됩니다. 포인트 수는 TTPOLYCURVEcpfx 구성원에 의해 지정됩니다. 다중선 또는 스플라인 곡선 유형은 wType 구성원에 의해 지정됩니다. 좌표 점 배열의 즉시 구조를 따릅니다. 곡선의 시작점에 apfx 구성원에 의해 지정됩니다.

문자 두 개 이상의 배분 형식을 포함할 수 있으므로 버퍼 TTPOLYGONHEADER 구조 및 데이터 중 하나 이상의 그룹을 포함합니다. 네이티브 버퍼의 이전 한 바로 다음 후속 배분 형식이 압축됩니다. 이전 곡선의 레코드의 마지막 지점 이후의 다음 바이트 TTPOLYGONHEADER 다음 배분 형식을 시작합니다.

이 샘플 코드는 각 배분 형식을 폼 3차원 선 세그먼트를 목록을 만들려면 GGO_NATIVE 버퍼 구문 트루타입 문자 윤곽선을 그립니다. 3차원 선 세그먼트를 목록은 다음 PolyBezier 사용하여 그려집니다. 버퍼의 유효성을 검사하도록 검사 DrawT2Outline 함수 코드입니다.

3차원 선 목록을 만들려면 먼저 목록의 버퍼 크기를 결정해야 합니다. 네 지점을 베지어 줄 정의합니다. PolyBezier 함수는 다음 줄의 시작 이전 줄의 끝점과 일치하는 위치 베지어 세그먼트 연속 줄 수 있는 것으로 점의 배열을 해석합니다. 따라서 세 점 추가 3차원 선 세그먼트가 설명하는 데 필요합니다.

GGO_NATIVE 버퍼 다중선 곡선 또는 정방형 B-스플라인 곡선 포함될 수 있습니다. B-스플라인 세 점을 정의하는 동안 두 개의 점은 선 세그먼트를 정의합니다. 각 형식 PolyBezier 사용하여 베지어 선을 그릴 것이므로, 최악의 시나리오 사례 여러 Beziers 선 세그먼트를 완전히 구성된 하나의 배분 형식을 확장할 때 발생합니다.

추가 곡선의 표현할 수 B-스플라인 곡선 표현 세그먼트 추가 점 하나만 필요하다는 유의하십시오. 해당 지점에 명시적으로 "B" 또는 해제 곡선 지점을 정의하고 암시적으로 추가 곡선 지점을 정의합니다. 따라 곡선의 중간점을 다음 "B" 지점으로 지점입니다. 따라서 추가 선 세그먼트 또는 추가 곡선 세그먼트가 세 가지 추가 베지어 줄 포인트 확장됩니다.

코드 포인트 버퍼에서 나타내는 가능한 최대 수를 결정할 수 있도록 전체 네이티브 버퍼 POINTFX 구조가 구성됩니다 가정합니다. 실제 때문에 구조 오버헤드가 배분 형식 및 곡선을 설명하는 약간 작습니다. 베지어 목록에 대한 버퍼 크기는 POINT 구조체를 통해 데이터 크기를 곱한 및 의해 세 곱한 지점 가능한 최대에 의해 지정됩니다. 세 개의 각 추가 선 세그먼트나 정방형 스플라인 세그먼트의 베지어로 변환할 때 필요한 추가 포인트 수를 것입니다.

베지어 버퍼를 할당한 후에는 코드에서 네이티브 버퍼 때 첫 번째 TTPOLYGONHEADER 시작하여 구문 분석합니다. 루프 반복 동안 코드를 한 배분 형식을 처리하고 이를 그립니다. 둘째 내부 루프는 각 곡선 형식을 구문 분석합니다.

다중선 곡선은 경우 (TT_PRIM_LINE), 다중선 각 선 세그먼트는 변환되어 AppendPolyLineToBezier 함수 사용하여 Beziers 목록에 추가됩니다. 곡선의 정방형 B-스플라인 (TT_PRIM_QSPLINE) 이면 AppendQuadBSplineToBezier 함수가 변환되며 정방형 B-스플라인 추가됩니다. 이러한 함수들은 루프를 해당 독립 제어점 곡선의 각 세그먼트 out 구문 분석합니다. 다음 줄 또는 스플라인 위해 베지어 변환되어 Beziers 목록에 추가된 것입니다.

3차원 선 쉽게 직선을 그릴 수 있습니다. 단순히 시작 및 끝 벡터 선 세그먼트 반대쪽 끝에 가리킵니다. 이 MakeBezierFromLine 함수에서가 수행됩니다.

정방형 스플라인 입방형 3차원 곡선 스플라인으로 변환할 수 있는 cubic 제어점 있는 quadratic 컨트롤 포인트 단위로 표현하는 필요합니다. 컨트롤 포인트 변환 수식은 MakeBezierFromQBSpline 함수는 찾을 수 있습니다.

해당 배분 형식을 그리기 전에 코드 경로를 CloseContour 함수를 호출하여 닫힙니다. 경우에만 시작 및 끝 지점을 Beziers 시퀀스로 일치하는 않으면 함수가 호출됩니다. 다음 PolyBezier 함수가 호출됩니다.

배분 형식을 사용하여 그린 후 다음 배분 형식 을 TTPOLYGONHEADER lpHeader 포인터가 현재 배분 형식을 레코드를 끝 지나 진행시키려면 찾을 수 없습니다. 네이티브 버퍼의 끝 지나 포인터 값이 결과 경우 모든 배분 형식 및 종료 코드를 처리했습니다.
/****************************************************************************
 *  FUNCTION   : IntFromFixed
 *  RETURNS    : int value approximating the FIXED value.
 ****************************************************************************/ 
int PASCAL NEAR IntFromFixed(FIXED f)
{
    if (f.fract >= 0x8000)
    return(f.value + 1);
    else
    return(f.value);
}

/****************************************************************************
 *  FUNCTION   : fxDiv2
 *  RETURNS    : (val1 + val2)/2 for FIXED values
 ****************************************************************************/ 
FIXED PASCAL NEAR fxDiv2(FIXED fxVal1, FIXED fxVal2)
{
    long l;

    l = (*((long far *)&(fxVal1)) + *((long far *)&(fxVal2)))/2;
    return(*(FIXED *)&l);
}

/****************************************************************************
 *  FUNCTION   : MakeBezierFromLine
 *
 *  PURPOSE    : Converts a line define by two points to a four point Bezier
 *               spline representation of the line in pPts.
 *
 *
 *  RETURNS    : number of Bezier points placed into the pPts POINT array.
 ****************************************************************************/ 
UINT MakeBezierFromLine( POINT *pPts, POINT startpt, POINT endpt )
{
    UINT cTotal = 0;

    // starting point of Bezier
    pPts[cTotal] = startpt;
    cTotal++;

    // 1rst Control, pt == endpoint makes Bezier a line
    pPts[cTotal].x = endpt.x;
    pPts[cTotal].y = endpt.y;
    cTotal++;

    // 2nd Control, pt == startpoint makes Bezier a line
    pPts[cTotal].x = startpt.x;
    pPts[cTotal].y = startpt.y;
    cTotal++;

    // ending point of Bezier
    pPts[cTotal] = endpt;
    cTotal++;
    
    return cTotal;
}

/****************************************************************************
 *  FUNCTION   : MakeBezierFromQBSpline
 *
 *  PURPOSE    : Converts a quadratic spline in pSline to a four point Bezier
 *               spline in pPts.
 *
 *
 *  RETURNS    : number of Bezier points placed into the pPts POINT array.
 ****************************************************************************/ 
UINT MakeBezierFromQBSpline( POINT *pPts, POINTFX *pSpline )
{
    POINT   P0,         // Quadratic on curve start point
            P1,         // Quadratic control point
            P2;         // Quadratic on curve end point
    UINT    cTotal = 0;

    // Convert the Quadratic points to integer
    P0.x = IntFromFixed( pSpline[0].x );
    P0.y = IntFromFixed( pSpline[0].y );
    P1.x = IntFromFixed( pSpline[1].x );
    P1.y = IntFromFixed( pSpline[1].y );
    P2.x = IntFromFixed( pSpline[2].x );
    P2.y = IntFromFixed( pSpline[2].y );

    // conversion of a quadratic to a cubic

    // Cubic P0 is the on curve start point
    pPts[cTotal] = P0;
    cTotal++;
    
    // Cubic P1 in terms of Quadratic P0 and P1
    pPts[cTotal].x = P0.x + 2*(P1.x - P0.x)/3;
    pPts[cTotal].y = P0.y + 2*(P1.y - P0.y)/3;
    cTotal++;

    // Cubic P2 in terms of Qudartic P1 and P2
    pPts[cTotal].x = P1.x + 1*(P2.x - P1.x)/3;
    pPts[cTotal].y = P1.y + 1*(P2.y - P1.y)/3;
    cTotal++;

    // Cubic P3 is the on curve end point
    pPts[cTotal] = P2;
    cTotal++;

    return cTotal;
}


/****************************************************************************
 *  FUNCTION   : AppendPolyLineToBezier
 *
 *  PURPOSE    : Converts line segments into their Bezier point 
 *               representation and appends them to a list of Bezier points. 
 *
 *               WARNING - The array must have at least one valid
 *               start point prior to the address of the element passed.
 *
 *  RETURNS    : number of Bezier points added to the POINT array.
 ****************************************************************************/ 
UINT AppendPolyLineToBezier( LPPOINT pt, POINTFX start, LPTTPOLYCURVE lpCurve )
{
    int     i;
    UINT    cTotal = 0;
    POINT   endpt;
    POINT   startpt;
    POINT   bezier[4];

    endpt.x = IntFromFixed(start.x);
    endpt.y = IntFromFixed(start.y);

    for (i = 0; i < lpCurve->cpfx; i++)
    {
        // define the line segment
        startpt = endpt;
        endpt.x = IntFromFixed(lpCurve->apfx[i].x);
        endpt.y = IntFromFixed(lpCurve->apfx[i].y);

        // convert a line to a bezier representation
        MakeBezierFromLine( bezier, startpt, endpt );

        // append the Bezier to the existing ones
                                    // Point 0 is Point 3 of previous.
        pt[cTotal++] = bezier[1];   // Point 1
        pt[cTotal++] = bezier[2];   // Point 2
        pt[cTotal++] = bezier[3];   // Point 3

    }

    return cTotal;
}


/****************************************************************************
 *  FUNCTION   : AppendQuadBSplineToBezier
 *
 *  PURPOSE    : Converts Quadratic spline segments into their Bezier point 
 *               representation and appends them to a list of Bezier points. 
 *
 *               WARNING - The array must have at least one valid
 *               start point prior to the address of the element passed.
 *
 *  RETURNS    : number of Bezier points added to the POINT array.
 ****************************************************************************/ 
UINT AppendQuadBSplineToBezier( LPPOINT pt, POINTFX start, LPTTPOLYCURVE lpCurve )
{
    WORD                i;
    UINT                cTotal = 0;
    POINTFX             spline[3];  // a Quadratic is defined by 3 points
    POINT               bezier[4];  // a Cubic by 4

    // The initial A point is on the curve.
    spline[0] = start;

    for (i = 0; i < lpCurve->cpfx;)
    {
        // The B point.
        spline[1] = lpCurve->apfx[i++];

        // Calculate the C point.
        if (i == (lpCurve->cpfx - 1))
        {
            // The last C point is described explicitly
            // i.e. it is on the curve.
            spline[2] = lpCurve->apfx[i++];
        }     
        else
        {
            // C is midpoint between B and next B point
            // because that is the on curve point of 
            // a Quadratic B-Spline.
            spline[2].x = fxDiv2(
                lpCurve->apfx[i-1].x,
                lpCurve->apfx[i].x
                );
            spline[2].y = fxDiv2(
                lpCurve->apfx[i-1].y,
                lpCurve->apfx[i].y
                );
        }

        // convert the Q Spline to a Bezier
        MakeBezierFromQBSpline( bezier, spline );
        
        // append the Bezier to the existing ones
                                    // Point 0 is Point 3 of previous.
        pt[cTotal++] = bezier[1];   // Point 1
        pt[cTotal++] = bezier[2];   // Point 2
        pt[cTotal++] = bezier[3];   // Point 3

        // New A point for next slice of spline is the 
        // on curve C point of this B-Spline
        spline[0] = spline[2];
    }

    return cTotal;
}

/****************************************************************************
 *  FUNCTION   : CloseContour
 *
 *  PURPOSE    : Adds a bezier line to close the circuit defined in pt.
 *
 *
 *  RETURNS    : number of points aded to the pt POINT array.
 ****************************************************************************/ 
UINT CloseContour( LPPOINT pt, UINT cTotal )
{
    POINT               endpt, 
                        startpt;    // definition of a line
    POINT               bezier[4];

    // connect the first and last points by a line segment
    startpt = pt[cTotal-1];
    endpt = pt[0];

    // convert a line to a bezier representation
    MakeBezierFromLine( bezier, startpt, endpt );

    // append the Bezier to the existing ones
                                // Point 0 is Point 3 of previous.
    pt[cTotal++] = bezier[1];   // Point 1
    pt[cTotal++] = bezier[2];   // Point 2
    pt[cTotal++] = bezier[3];   // Point 3

    return 3;
}

/****************************************************************************
 *  FUNCTION   : DrawT2Outline
 *
 *  PURPOSE    : Decode the GGO_NATIVE outline, create a sequence of Beziers
 *               for each contour, draw with PolyBezier.  Color and relative 
 *               positioning provided by caller. The coordinates of hDC are
 *               assumed to have MM_TEXT orientation.
 *
 *               The outline data is not scaled. To draw a glyph unhinted
 *               the caller should create the font at its EMSquare size
 *               and retrieve the outline data. Then setup a mapping mode
 *               prior to calling this function.
 *
 *  RETURNS    : none.
 ****************************************************************************/ 
void DrawT2Outline(HDC hDC, LPTTPOLYGONHEADER lpHeader, DWORD size) 
{
    WORD                i;
    UINT                cTotal = 0; // Total points in a contour.
    LPTTPOLYGONHEADER   lpStart;    // the start of the buffer
    LPTTPOLYCURVE       lpCurve;    // the current curve of a contour
    LPPOINT             pt;         // the bezier buffer
    POINTFX             ptStart;    // The starting point of a curve
    DWORD               dwMaxPts = size/size of(POINTFX); // max possible pts.
    DWORD               dwBuffSize;

    dwBuffSize = dwMaxPts *     // Maximum possible # of contour points.
                 sizeof(POINT) * // sizeof buffer element
                 3;             // Worst case multiplier of one additional point
                                // of line expanding to three points of a bezier

   lpStart = lpHeader;
   pt = (LPPOINT)malloc( dwBuffSize );

    // Loop until we have processed the entire buffer of contours.
    // The buffer may contain one or more contours that begin with
    // a TTPOLYGONHEADER. We have them all when we the end of the buffer.
    while ((DWORD)lpHeader < (DWORD)(((LPSTR)lpStart) + size) && pt != NULL)
    {
        if (lpHeader->dwType == TT_POLYGON_TYPE)
        // Draw each coutour, currently this is the only valid
        // type of contour.
        {
            // Convert the starting point. It is an on curve point.
            // All other points are continuous from the "last" 
            // point of the contour. Thus the start point the next
            // bezier is always pt[cTotal-1] - the last point of the 
            // previous bezier. See PolyBezier.
            cTotal = 1;
            pt[0].x = IntFromFixed(lpHeader->pfxStart.x);
            pt[0].y = IntFromFixed(lpHeader->pfxStart.y);

            // Get to first curve of contour - 
            // it starts at the next byte beyond header
            lpCurve = (LPTTPOLYCURVE) (lpHeader + 1);

            // Walk this contour and process each curve( or line ) segment 
            // and add it to the Beziers
            while ((DWORD)lpCurve < (DWORD)(((LPSTR)lpHeader) + lpHeader->cb))
            {
                //**********************************************
                // Format assumption:
                //   The bytes immediately preceding a POLYCURVE
                //   structure contain a valid POINTFX.
                // 
                //   If this is first curve, this points to the 
                //      pfxStart of the POLYGONHEADER.
                //   Otherwise, this points to the last point of
                //      the previous POLYCURVE.
                // 
                //   In either case, this is representative of the
                //      previous curve's last point.
                //**********************************************

                ptStart = *(LPPOINTFX)((LPSTR)lpCurve - sizeof(POINTFX));
                if (lpCurve->wType == TT_PRIM_LINE)
                {
                    // convert the line segments to Bezier segments
                    cTotal += AppendPolyLineToBezier( &pt[cTotal], ptStart, lpCurve );
                    i = lpCurve->cpfx;
                }
                else if (lpCurve->wType == TT_PRIM_QSPLINE)
                {
                    // Decode each Quadratic B-Spline segment, convert to bezier,
                    // and append to the Bezier segments
                    cTotal += AppendQuadBSplineToBezier( &pt[cTotal], ptStart, lpCurve );
                    i = lpCurve->cpfx;
                }
                else
                    // Oops! A POLYCURVE format we don't understand.
                    ; // error, error, error

            // Move on to next curve in the contour.
            lpCurve = (LPTTPOLYCURVE)&(lpCurve->apfx[i]);
            }

            // Add points to close the contour.
            // All contours are implied closed by TrueType definition.
            // Depending on the specific font and glyph being used, these
            // may not always be needed.
            if ( pt[cTotal-1].x != pt[0].x || pt[cTotal-1].y != pt[0].y )
            {
                cTotal += CloseContour( pt, cTotal );
            }

            // flip coordinates to get glyph right side up (Windows coordinates)
            // TT native coordiantes are zero originate at lower-left.
            // Windows MM_TEXT are zero originate at upper-left.
            for (i = 0; i < cTotal; i++)
                pt[i].y = 0 - pt[i].y;

            // Draw the contour
            PolyBezier( hDC, pt, cTotal );
        }
        else
            // Bad, bail, must have a bogus buffer.
            break; // error, error, error

        // Move on to next Contour.
        // Its header starts immediate after this contour
        lpHeader = (LPTTPOLYGONHEADER)(((LPSTR)lpHeader) + lpHeader->cb);
    }

    free( pt );
}
				

참조

트루타입 사양에 대한 자세한 내용은 참조하십시오.
Microsoft TrueType Specifications (http://www.microsoft.com/typography/tt/tt.htm)

또한 사용할 Microsoft 개발자 네트워크 라이브러리 CD 의 사양 아래에 있습니다.

속성

기술 자료: 243285 - 마지막 검토: 2007년 2월 12일 월요일 - 수정: 1.5
본 문서의 정보는 다음의 제품에 적용됩니다.
  • Microsoft Win32 Application Programming Interface
  • Microsoft Windows XP Professional
  • the operating system: Microsoft Windows XP 64-Bit Edition
키워드:?
kbmt kbdswgdi2003swept kbdraw kbfont kbgdi kbhowto KB243285 KbMtko
기계 번역된 문서
중요: 본 문서는 전문 번역가가 번역한 것이 아니라 Microsoft 기계 번역 소프트웨어로 번역한 것입니다. Microsoft는 번역가가 번역한 문서 및 기계 번역된 문서를 모두 제공하므로 Microsoft 기술 자료에 있는 모든 문서를 한글로 접할 수 있습니다. 그러나 기계 번역 문서가 항상 완벽한 것은 아닙니다. 따라서 기계 번역 문서에는 마치 외국인이 한국어로 말할 때 실수를 하는 것처럼 어휘, 구문 또는 문법에 오류가 있을 수 있습니다. Microsoft는 내용상의 오역 또는 Microsoft 고객이 이러한 오역을 사용함으로써 발생하는 부 정확성, 오류 또는 손해에 대해 책임을 지지 않습니다. Microsoft는 이러한 문제를 해결하기 위해 기계 번역 소프트웨어를 자주 업데이트하고 있습니다.

피드백 보내기

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com