home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 26 / AACD 26.iso / AACD / Graphics / sKulpt / skulpt-src / FontOutliner.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-07-08  |  9.5 KB  |  281 lines

  1. #define STRICT
  2.  
  3. // Includes standard Windows
  4. #include <windows.h>
  5. #include <windowsx.h>
  6. #include <time.h>
  7. #include <stdlib.h>
  8. #include <malloc.h>
  9. #include <memory.h>
  10. #include <stdio.h>
  11.  
  12. // Includes D3D
  13. #define  D3D_OVERLOADS
  14. #include <ddraw.h>
  15. #include <d3d.h>
  16. #include <d3dx.h>
  17.  
  18. // Includes utilitaires D3D
  19. #include "d3dmath.h"
  20. #include "d3dutil.h"
  21. #include "D3DEnum.h"
  22.  
  23. // Ids Resources
  24. #include "resource.h"
  25.  
  26. // Constantes
  27. #include "const.h"
  28.  
  29. // Types
  30. #include "types.h"
  31.  
  32. // Variables globales projet
  33. #include "vars.h"
  34.  
  35. // Prototypes fonctions autres modules
  36. #include "proto.h"
  37.  
  38. // Macros
  39. #include "macros.h"
  40.  
  41. // Variables statiques au module
  42. static BOOL bTracking = FALSE;                            // Poursuite curseur en cours o/n (WM_LBUTTONDOWN / WM_MOUSEMOVE)
  43. static WPARAM wModifier;                                // Mémorisé sur le LBUTTONDOWN : SHIFT / CTRL / ...
  44. static HBRUSH hbrDkBlueSk, hbrLtBlueSk;                        // Brosses de remplissage
  45. static HPEN hpenWhite, hpenGrey, hpenCyan, hpenYellow, hpenPink, hpenDkBlueSk, hpenRed;    // Crayons
  46. static HFONT hFont;
  47.  
  48.  
  49. void vAddTextOutline(void)
  50. {
  51. #define XDC_HEADER    0
  52. #define XDC_CURVE    1
  53.  
  54.     GLYPHMETRICS sGlyphMetrics;        // Récupérer infos de kerning du caractère courant
  55.     MAT2 sMatrix;                    // Matrice identité (pourrait servir à faire tourner les caractères)
  56.     WinThings *    psWinProps            // Pour récuperer un HDC avec font
  57.         = (WinThings *) GetWindowLong(hWndFace, 0);
  58.     CHOOSEFONT cf;                    // structure common dialog box 
  59.     static LOGFONT lf;                // structure logical font 
  60.     static DWORD rgbCurrent;        // current text color
  61.     HFONT hfont, hfontPrev = NULL;
  62.     float fFontScale = 1.f;
  63.  
  64.     // Initialize CHOOSEFONT
  65.     ZeroMemory(&cf, sizeof(CHOOSEFONT));
  66.     cf.lStructSize = sizeof (CHOOSEFONT);
  67.     cf.hwndOwner = NULL;
  68.     cf.lpLogFont = &lf;
  69.     cf.rgbColors = rgbCurrent;
  70.     cf.Flags = CF_BOTH | CF_TTONLY | CF_NOSCRIPTSEL | CF_INITTOLOGFONTSTRUCT;
  71.     strcpy(lf.lfFaceName, "Arial");
  72.  
  73.     if (ChooseFont(&cf)==TRUE)
  74.     {
  75.         hfont = CreateFontIndirect(cf.lpLogFont);
  76.         hfontPrev = (HFONT) SelectObject(psWinProps ->hdcDBuf, hfont);
  77.         fFontScale = cf.iPointSize / 40.f;
  78.     }
  79.  
  80.     // Saisir la chaîne
  81.     if (DialogBoxParam(hInst, MAKEINTRESOURCE(IDD_STRING), NULL, bStringDlgProc, 0))
  82.         return;
  83.  
  84.     // Régler la matrice sur l'identité (pour ne pas faire tourner les caractères)
  85.     sMatrix.eM11.value = sMatrix.eM22.value = 1;
  86.     sMatrix.eM12.value = sMatrix.eM21.value =
  87.     sMatrix.eM11.fract = sMatrix.eM22.fract = sMatrix.eM12.fract = sMatrix.eM21.fract = 0;
  88.  
  89.     // Pour chaque caractère de la chaîne
  90.     for (char *pChar = cString ; *pChar ; pChar++)
  91.     {
  92.         TTPOLYGONHEADER    *pPolyHeader;
  93.         TTPOLYCURVE *pPolyCurve;
  94.         DWORD iBufSize;
  95.         BOOL bState = XDC_HEADER;
  96.         POINTFX *pPoints;
  97.         BYTE *pFullBuffer, *pBlock, *pCurve;
  98.         int iVert0, iVert1, iVert2;
  99.         float fValue, fKmin = 100000.f, fKmax = -100000.f;
  100.         D3DVECTOR dVec = Cursor1;
  101.         
  102.         // Suppression des accents
  103.         if (strchr("àâä", *pChar))    *pChar = 'a';
  104.         if (strchr("éèêë", *pChar))    *pChar = 'e';
  105.         if (strchr("ïî", *pChar))    *pChar = 'i';
  106.         if (strchr("ôö", *pChar))    *pChar = 'o';
  107.         if (strchr("ûü", *pChar))    *pChar = 'u';
  108.         if (strchr("ÿ", *pChar))    *pChar = 'y';
  109.  
  110.         // Si le caractère est un espace, on fait seulement avancer le curseur
  111.         if (*pChar == ' ')
  112.         {
  113.             switch(lWActive)
  114.             {
  115.                 case XDC_WID_TOP : // X et Z
  116.                 case XDC_WID_FACE : // X et Y
  117.                     Cursor1.x += fFontScale * (sGlyphMetrics.gmBlackBoxX / 2.f);
  118.                     break;
  119.                         
  120.                 case XDC_WID_SIDE : // Z et Y
  121.                     Cursor1.z += fFontScale * (sGlyphMetrics.gmBlackBoxX / 2.f);
  122.                     break;
  123.             }
  124.             continue;
  125.         }
  126.  
  127.         // Récupérer la taille du buffer de courbes définissant le caractère courant
  128.         iBufSize = GetGlyphOutline(psWinProps ->hdcDBuf, *pChar, GGO_NATIVE, &sGlyphMetrics, 0, NULL, &sMatrix);
  129.         
  130.         // Si l'outliner n'est pas capable de générer le buffer pour le caractère, au suivant.
  131.         if (iBufSize == 0xFFFFFFFF) continue;
  132.  
  133.         // Allouer le buffer de courbes
  134.         if (!(pBlock = pFullBuffer = (unsigned char *) malloc(iBufSize)))
  135.             continue;
  136.  
  137.         // Récupérer le buffer de courbes
  138.         GetGlyphOutline(psWinProps ->hdcDBuf, *pChar, GGO_NATIVE, &sGlyphMetrics, iBufSize, pFullBuffer, &sMatrix);
  139.         
  140.         // Pour chaque bloc en-tête / courbe(s)
  141.         while (pBlock < pFullBuffer + iBufSize - 1)
  142.         {
  143.             switch(bState)
  144.             {
  145.                 case XDC_HEADER: // Si on est sur un en-tête
  146.                     // Récupérer un pointeur sur le header
  147.                     pPolyHeader = (TTPOLYGONHEADER *) pBlock;
  148.                     
  149.                     // Créer le point de départ de l'enveloppe du caractère, et mémoriser son indice
  150.                     switch(lWActive)
  151.                     {
  152.                         case XDC_WID_TOP : // X et Z
  153.                             dVec.x = Cursor1.x + fFontScale * (pPolyHeader -> pfxStart.x.value + (float) (pPolyHeader -> pfxStart.x.fract) / 65536.f);
  154.                             dVec.z = Cursor1.z + fFontScale * (pPolyHeader -> pfxStart.y.value + (float) (pPolyHeader -> pfxStart.y.fract) / 65536.f);
  155.                             break;
  156.                                 
  157.                         case XDC_WID_FACE : // X et Y
  158.                             dVec.x = Cursor1.x + fFontScale * (pPolyHeader -> pfxStart.x.value + (float) (pPolyHeader -> pfxStart.x.fract) / 65536.f);
  159.                             dVec.y = Cursor1.y + fFontScale * (pPolyHeader -> pfxStart.y.value + (float) (pPolyHeader -> pfxStart.y.fract) / 65536.f);
  160.                             break;
  161.                                 
  162.                         case XDC_WID_SIDE : // Z et Y
  163.                             dVec.z = Cursor1.z + fFontScale * (pPolyHeader -> pfxStart.x.value + (float) (pPolyHeader -> pfxStart.x.fract) / 65536.f);
  164.                             dVec.y = Cursor1.y + fFontScale * (pPolyHeader -> pfxStart.y.value + (float) (pPolyHeader -> pfxStart.y.fract) / 65536.f);
  165.                             break;
  166.                     }
  167.                     iVert0 = iVert1 = iMakeVertex(dVec, XDC_ALLOWSAME);
  168.                     Vertices[iVert0].bSelected = TRUE;
  169.  
  170.                     // Décaler le pointeur de bloc sur le bloc courant (qui est une courbe)
  171.                     pBlock += sizeof(TTPOLYGONHEADER);
  172.                     bState = XDC_CURVE;
  173.  
  174.                     // Special SG Kludge : ??? la taille indiquée pour le buffer est apparemment 4 x nb_headers plus grosse que la réalité...
  175.                     iBufSize -= 4;
  176.                     break;
  177.  
  178.                 case XDC_CURVE: // Si on est sur une courbe
  179.                     // Récupérer un pointeur sur la première courbe du bloc
  180.                     pCurve = pBlock;
  181.  
  182.                     // Décaler le pointeur de bloc sur le bloc courant (qui est une courbe ou un header)
  183.                     pBlock += ((pPolyHeader -> cb) - sizeof(TTPOLYGONHEADER));
  184.                     
  185.                     // Pour chaque courbe du bloc
  186.                     do
  187.                     {
  188.                         // Récupérer un pointeur sur la structure courbe
  189.                         pPolyCurve = (TTPOLYCURVE *) pCurve;
  190.  
  191.                         // Calculer la taille de la courbe (pour ensuite passer à la suivante dansle bloc)
  192.                         int iSize = pPolyCurve -> cpfx * sizeof(pPolyCurve -> apfx) + sizeof(pPolyCurve -> cpfx) + sizeof(pPolyCurve -> wType);
  193.                         
  194.                         // Récupérer un pointeur sur le tableau de points de la courbe
  195.                         pPoints = &(pPolyCurve -> apfx[0]);
  196.  
  197.                         // Si la courbe est d'un type connu
  198.                         if (    pPolyCurve -> wType == TT_PRIM_LINE
  199.                             ||    pPolyCurve -> wType == TT_PRIM_QSPLINE
  200.                             ||    pPolyCurve -> wType == TT_PRIM_CSPLINE)
  201.                             // Pour chaque point de la courbe
  202.                             for (int iPoint = 0 ; iPoint < pPolyCurve -> cpfx ; iPoint++)
  203.                             {
  204.                                 // Dessiner le point et tracer une arête avec le précédent
  205.                                 switch(lWActive)
  206.                                 {
  207.                                     case XDC_WID_TOP : // X et Z
  208.                                         dVec.x = Cursor1.x + fFontScale * (pPoints[iPoint].x.value + (float) (pPoints[iPoint].x.fract) / 65536.f);
  209.                                         dVec.z = Cursor1.z + fFontScale * (pPoints[iPoint].y.value + (float) (pPoints[iPoint].y.fract) / 65536.f);
  210.                                         break;
  211.                                             
  212.                                     case XDC_WID_FACE : // X et Y
  213.                                         dVec.x = Cursor1.x + fFontScale * (pPoints[iPoint].x.value + (float) (pPoints[iPoint].x.fract) / 65536.f);
  214.                                         dVec.y = Cursor1.y + fFontScale * (pPoints[iPoint].y.value + (float) (pPoints[iPoint].y.fract) / 65536.f);
  215.                                         break;
  216.                                             
  217.                                     case XDC_WID_SIDE : // Z et Y
  218.                                         dVec.z = Cursor1.z + fFontScale * (pPoints[iPoint].x.value + (float) (pPoints[iPoint].x.fract) / 65536.f);
  219.                                         dVec.y = Cursor1.y + fFontScale * (pPoints[iPoint].y.value + (float) (pPoints[iPoint].y.fract) / 65536.f);
  220.                                         break;
  221.                                 }
  222.                                 iVert2 = iMakeVertex(dVec, XDC_ALLOWSAME);
  223.                                 iMakeEdge(iVert2, iVert1);
  224.  
  225.                                 // Shifter le précédent
  226.                                 iVert1 = iVert2;
  227.  
  228.                                 // Ajuster les mini / maxi du kerning pour ce caractère
  229.                                 fValue = fFontScale * (pPoints[iPoint].x.value + (float) (pPoints[iPoint].x.fract) / 65536.f);
  230.                                 if (fKmin > fValue) fKmin = fValue;
  231.                                 if (fKmax < fValue) fKmax = fValue;
  232.  
  233.                                 fValue = fFontScale * (pPolyHeader -> pfxStart.x.value + (float) (pPolyHeader -> pfxStart.x.fract) / 65536.f);
  234.                                 if (fKmin > fValue) fKmin = fValue;
  235.                                 if (fKmax < fValue) fKmax = fValue;
  236.                             }
  237.  
  238.                         // Passer à la courbe suivante dans le bloc
  239.                         pCurve += iSize;
  240.  
  241.                     } while (pCurve < pBlock && pCurve < pFullBuffer + iBufSize);
  242.  
  243.                     // Refermer la courbe si elle ne l'est pas encore
  244.                     //if (pPolyCurve -> wType == TT_PRIM_LINE)
  245.                     if (-1 == iFindEdge(iVert2, iVert0))
  246.                         iMakeEdge(iVert2, iVert0);
  247.  
  248.                     // Le prochain bloc est un header
  249.                     bState = XDC_HEADER;
  250.                     break;
  251.             }
  252.         }
  253.  
  254.         // Libérer le buffer de courbes
  255.         free(pFullBuffer);
  256.  
  257.         // Avancer le curseur
  258.         switch(lWActive)
  259.         {
  260.             case XDC_WID_TOP : // X et Z
  261.             case XDC_WID_FACE : // X et Y
  262.                 Cursor1.x += 1.15f * (fKmax - fKmin);
  263.                 break;
  264.                     
  265.             case XDC_WID_SIDE : // Z et Y
  266.                 Cursor1.z += 1.15f * (fKmax - fKmin);
  267.                 break;
  268.         }
  269.     }
  270.  
  271.     // Remettre la fonte par défaut du DC si on l'a changée
  272.     if (hfontPrev)
  273.     {
  274.         SelectObject(psWinProps ->hdcDBuf, hfontPrev);
  275.         
  276.         // Libérer la fonte créée
  277.         DeleteFont(hfont);
  278.     }
  279.  
  280. }
  281.