Al momento sei offline in attesa che la connessione Internet venga ristabilita

How to: Disegna contorni icona TrueType

Il supporto per Windows XP è terminato

Il supporto Microsoft per Windows XP è terminato l'8 aprile 2014. Questa modifica ha interessato gli aggiornamenti software e le opzioni di sicurezza. Ulteriori informazioni su come continuare a essere protetti.

Il presente articolo è stato tradotto tramite il software di traduzione automatica di Microsoft e non da una persona. Microsoft offre sia articoli tradotti da persone fisiche sia articoli tradotti automaticamente da un software, in modo da rendere disponibili tutti gli articoli presenti nella nostra Knowledge Base nella lingua madre dell’utente. Tuttavia, un articolo tradotto in modo automatico non è sempre perfetto. Potrebbe contenere errori di sintassi, di grammatica o di utilizzo dei vocaboli, più o meno allo stesso modo di come una persona straniera potrebbe commettere degli errori parlando una lingua che non è la sua. Microsoft non è responsabile di alcuna imprecisione, errore o danno cagionato da qualsiasi traduzione non corretta dei contenuti o dell’utilizzo degli stessi fatto dai propri clienti. Microsoft, inoltre, aggiorna frequentemente il software di traduzione automatica.

243285
Sommario
La funzione API Win32 GetGlyphOutline restituita icona nativo strutturare i dati da un tipo di carattere TrueType. Per disegnare una struttura di glifo TrueType, i dati devono essere convertiti dalla relativa definizione B-spline nativo a una sequenza di definizioni di riga di Bézier. Quindi la funzione di API Win32 di PolyBezier può essere utilizzata per disegnare la struttura.
Informazioni
La funzione di GetGlyphOutline nella programmazione Interface(API) Win32 applicazioni è possibile recuperare una struttura di TrueType. L'opzione di formattazione GGO_NATIVE riempie un buffer con curve B-spline Quadratic per una struttura di TrueType. B-spline quadratiche vengono utilizzati da TrueType per descrivere la struttura di icona in un file di carattere TrueType. Per disegnare queste curve struttura una possibile implementare una funzione di disegno B-spline oppure utilizzare la funzione PolyBezier dall'API Win32.

Quadratiche curve B-spline sono una classe di curve parametrica che consente di definire il percorso di più segmenti della curva tramite alcuni punti di controllo. Una curva Quadratic è una seconda curva parametrica ordine. Non vi è alcuna funzione nell'API per disegnare una Spline Quadratic direttamente ma se il Quadratic viene convertito in un cubica con l'API Win32 possono essere disegnato funzione per disegnare una curva di Bézier, chiamato PolyBezier .

In generale, quadratiche curve B-spline in particolare e parametrica curve sono un argomento well-researched di elementi grafici in informatica. Possono inoltre essere molto complesse. Gli algoritmi sono stati pubblicati in vari testi che è possibile utilizzare per implementare una funzione per disegnare una Spline Quadratic, ma che descrive un algoritmo di tali esula dall'ambito di questo articolo.

La funzione PolyBezier possibile disegnare una Spline Quadratic perché una curva di Bézier è una curva parametrica cubica o terza nell'ordine. Poiché una Spline Quadratic è un'equazione ordine seconda, può essere espresso in termini dell'equazione di cubi di ordine superiore. Sebbene un'equazione per esprimere un quadratic come un cubica viene specificata nel codice di esempio, la derivazione è descritto non in questo articolo.

Il codice di esempio in questo articolo è una dimostrazione di come analizzare un buffer di glifi GGO_NATIVE restituito dalla funzione GetGlyphOutline . Buffer restituito dal flag di formato GGO_NATIVE è conforme alla struttura TTPOLYGONHEADER . La struttura TTPOLYGONHEADER e i dati che segue immediatamente costituiscono una distribuzione di un glifo TrueType. Un profilo è un percorso completo di curve viene chiuso in modo implicito se non viene restituito in modo esplicito in questo modo.

Vedere la documentazione Platform SDK nelle strutture TTPOLYGONHEADER e TTPOLYCURVE .

Una distribuzione di glifo è costituito da più segmenti di curva rappresentati da strutture TTPOLYCURVE . In una distribuzione di TTPOLYGONHEADER è seguito da uno o più strutture TTPOLYCURVE e dati di coordinate del punto. Il membro pfxStart fornisce il punto di coordinata iniziale della distribuzione. Il numero di record di curva che seguono il TTPOLYGONHEADER è determinato dal membro cb . Il punto di partenza è relativa all'origine dell'icona. L'origine di un glifo è l'angolo inferiore sinistro del carattere alla linea di base del carattere.

Ogni record di curva TTPOLYCURVE (un segmento di curva) è costituito da punti di controllo B-spline Quadratic o semplici punti di polilinea. Il numero di punti è determinato dal membro cpfx TTPOLYCURVE . Dal membro wType viene assegnato il tipo di curva di spline o polilinea. Matrice di punti delle coordinate seguire immediatamente la struttura. Il punto iniziale della curva viene assegnato dal membro apfx .

Poiché un glifo può contenere più di una distribuzione, il buffer contiene uno o più gruppi di TTPOLYGONHEADER strutture e dati. Distribuzioni successive vengono compressi immediatamente dopo quello precedente nel buffer nativo. La distribuzione successiva inizia con un TTPOLYGONHEADER dal byte successivo oltre l'ultimo punto del record precedente curva.

Questo codice di esempio consente di disegnare la struttura di un glifo TrueType analizzando il buffer GGO_NATIVE per creare un elenco di segmenti di linea Bézier che costituiscono ogni distribuzione. Elenco di segmenti di Bezier riga viene quindi disegnato utilizzando PolyBezier . Il codice che analizza il buffer è la funzione DrawT2Outline .

Il primo passaggio per creare un elenco di righe di Bézier consiste nel determinare la dimensione del buffer per l'elenco. Quattro punti definiscono le righe di Bézier. La funzione PolyBezier interpreta una matrice di punti come una riga continua di segmenti di Bezier in cui l'inizio della riga successiva è che coincidono con l'endpoint della riga precedente. Di conseguenza, solo tre punti sono necessari per descrivere un segmento di linea Bézier aggiuntivo.

Il buffer GGO_NATIVE può contenere una curva di polilinea o una curva B-spline Quadratic. Due punti definiscono un segmento di linea durante tre punti definiscono una B-spline. Poiché ogni tipo è essere disegnato con una linea di Bézier utilizzando PolyBezier, nello scenario peggiore viene si una verifica quando una distribuzione che è costituita interamente da segmenti di linea si espande per Beziers più.

Si noti che per esprimere una curva ulteriore segmento in una rappresentazione di curva B-spline richiede solo un punto supplementare. Tale punto definisce esplicitamente "B" o disattivare curva scegliere e in modo implicito definisce aggiuntiva nel punto della curva. Il punto di curva su è il punto centrale al successivo punto di "B". Pertanto o un segmento di linea aggiuntiva che un segmento di curva ulteriori si espanderà per tre ulteriori punti di una riga di Bézier.

Nel codice si presuppone che l'intero buffer nativo sarà composto da POINTFX strutture in modo che è possibile determinare il maggior numero possibile di punti rappresentato da un buffer di. Il numero effettivo è leggermente inferiore poiché è presente un sovraccarico della struttura di descrivere le distribuzioni e le curve. La dimensione del buffer per l'elenco di Bézier è determinata dal numero massimo di punti di moltiplicato per il dati dimensione di una struttura POINT e moltiplicato per tre. Tre è il numero di punti aggiuntivi necessari per ogni segmento di linea aggiuntiva o di un segmento di spline quadratica quando convertito in un tipo di Bézier.

Una volta che è stato allocato il buffer di Bézier il codice analizza il buffer nativo avviando nel primo TTPOLYGONHEADER . Durante un'iterazione del ciclo il codice elabora una distribuzione e disegno. Un secondo ciclo interno analizza ciascun tipo di curva.

In caso di una curva della polilinea (TT_PRIM_LINE), ogni segmento di linea della polilinea convertita viene aggiunto all'elenco di Beziers con la funzione AppendPolyLineToBezier . Se si utilizza la curva B-spline Quadratic (TT_PRIM_QSPLINE), la funzione AppendQuadBSplineToBezier converte e aggiunge Quadratic B-spline. Ciascuna di queste funzioni utilizza un ciclo per analizzare da ogni segmento della curva in relativi punti di controllo indipendenti. Quindi la riga o la spline viene convertito in un Bézier e aggiunto all'elenco di Beziers.

Una riga di Bézier possibile disegnare una linea retta facilmente. L'inizio e fine vettori posizionare semplicemente all'estremità opposta del segmento di linea. Questa operazione viene eseguita nella funzione MakeBezierFromLine .

Per convertire una spline quadratica in una spline di Bézier cubica, è necessario esprimere punti di controllo del cubica i in termini di punti di controllo del quadratic il. L'equazione per tradurre i punti di controllo si trova nella funzione MakeBezierFromQBSpline .

Prima di disegnare la distribuzione, il codice garantisce che il percorso sia chiuso chiamando la funzione CloseContour . La funzione viene chiamata solo se il punto di fine della sequenza di Beziers iniziale e non sono che coincidono. Quindi viene chiamata la funzione PolyBezier .

Dopo la distribuzione è disegnata, TTPOLYGONHEADER della distribuzione successivo Trova per far avanzare il puntatore lpHeader oltre la fine dei record del profilo corrente. Se questo dà come risultato un valore di puntatore oltre la fine del buffer nativo, il codice ha elaborato tutte le distribuzioni e la chiusura.
/**************************************************************************** *  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 );}				
Riferimenti
Per ulteriori informazioni sulla specifica TrueType vedere:
Microsoft TrueType Specifications (http://www.microsoft.com/typography/tt/tt.htm)

Disponibile anche nel Microsoft Developer Network Library CD in specifiche.

Avviso: questo articolo è stato tradotto automaticamente

Proprietà

ID articolo: 243285 - Ultima revisione: 02/12/2007 19:26:04 - Revisione: 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 KbMtit
Feedback
cript>