Ejemplo n.º 1
0
sInt sFont2D::GetWidth(const sChar *text,sInt len)
{
  SIZE out;

  if(len==-1) len=sGetStringLen(text);
  if(len==0) return 0;

  SelectObject(sGDIDCOffscreen,prv->Font);
  GetTextExtentPoint32W(sGDIDCOffscreen,text,len,&out);
  sInt width = out.cx;

  if(1)  // exact calculation, usefull for italics
  {
    sInt abcC;
    sInt ch = text[len-1];
    if(ch < NUMABC)
      abcC = prv->Widths[ch].abcC;
    else
    {
      ABC abc;
      GetCharABCWidths(sGDIDCOffscreen,ch,ch,&abc);
      abcC = abc.abcC;
    }

    if(abcC<0)
      width -= abcC;
  }

  return width;
}
Ejemplo n.º 2
0
void sFont2D::Init(const sChar *name,sInt size,sInt flags,sInt width)
{
  Exit();

  TEXTMETRIC tm;

  prv = new sFont2DPrivate;
  prv->Font=0;
  prv->BackPen = 0;

  if (name && name[0])
  {
    LOGFONTW log;
    sClear(log);
    log.lfHeight = size;
    log.lfWidth = width;
    log.lfCharSet = DEFAULT_CHARSET;
    if(flags & sF2C_BOLD)
      log.lfWeight = FW_BOLD;
    if(flags & sF2C_ITALICS)
      log.lfItalic = 1;
    if(flags & sF2C_UNDERLINE)
      log.lfUnderline = 1;
    if(flags & sF2C_STRIKEOUT)
      log.lfStrikeOut = 1;
    if(flags & sF2C_SYMBOLS)
      log.lfCharSet = SYMBOL_CHARSET;
    if(flags & sF2C_NOCLEARTYPE)
      log.lfQuality = ANTIALIASED_QUALITY;
    sCopyString(log.lfFaceName,name,LF_FACESIZE);
    prv->Font = CreateFontIndirectW(&log);
  }

  if (!prv->Font) // no font found -> get default Windows font
  {
    NONCLIENTMETRICS ncm;
    sClear(ncm);
    ncm.cbSize=sizeof(ncm);
    SystemParametersInfo(SPI_GETNONCLIENTMETRICS,sizeof(ncm),&ncm,0);
    prv->Font = CreateFontIndirectW(&ncm.lfMessageFont);
  }

  prv->BackColor = GDICOL(0xffffff);
  prv->TextColor = GDICOL(0x000000);

  // Get font metrics. must create a DC for this!
  HDC dc = GetDC(sHWND);
  HGDIOBJ oldfont = SelectObject(dc,prv->Font);
  GetTextMetricsW(dc,&tm);
  GetCharABCWidths(dc,0,NUMABC-1,prv->Widths);
  SelectObject(dc,oldfont);
  ReleaseDC(sHWND,dc);

  prv->Baseline = tm.tmAscent;
  prv->Height = tm.tmHeight;
  prv->CharHeight = tm.tmHeight - tm.tmInternalLeading;
}
Ejemplo n.º 3
0
sFont2D::sLetterDimensions sFont2D::sGetLetterDimensions(const sChar letter)
{
  sLetterDimensions result;

  SelectObject(sGDIDCOffscreen,prv->Font);

  ABC abc;
  
  if(GetCharABCWidths(sGDIDCOffscreen,letter,letter,&abc))
  {
    result.Pre      = abc.abcA;
    result.Cell     = abc.abcB;
    result.Post     = abc.abcC;
    result.Advance  = abc.abcA + abc.abcB + abc.abcC;

    MAT2 mat;
    sClear(mat);
    mat.eM11.value = 1;
    mat.eM22.value = 1;
    GLYPHMETRICS metrics;

    if (GDI_ERROR != GetGlyphOutline(sGDIDCOffscreen, letter, GGO_METRICS, &metrics, 0, 0, &mat))
    {
      result.Height = metrics.gmBlackBoxY;
      result.OriginY = metrics.gmptGlyphOrigin.y;
    }
    else
    {
      SIZE size;
      GetTextExtentPoint32(sGDIDCOffscreen, &letter, 1, &size);
      result.Height = size.cy;
      result.OriginY = size.cy;
    }
  }
  else
  {
    SIZE size;
    GetTextExtentPoint32(sGDIDCOffscreen,&letter,1,&size);
    
    result.Pre      = 0;
    result.Cell     = size.cx;
    result.Post     = 0;
    result.Advance  = size.cx;
    result.Height   = size.cy;
    result.OriginY  = size.cy;
  }
  

  return result;
}
Ejemplo n.º 4
0
///////////////////////////////////////////////////////////////////////////////
// Descripcion:
// - Crea la fuente true type, pero NO la selecciona. 
// Parametros:
// - hdc. DC a la superficie sobre la que se va a crear la fuente.
// - swDeciPt. Tamaño de la fuentes en puntos por 10. Si nuestra fuente va a
//   tener un tamaño de 16, debera de valer 16x10 = 160.
// Devuelve:
// Notas:
///////////////////////////////////////////////////////////////////////////////
void 
CFont::CreateTTFont(const HDC& hdc, const sword& swDeciPt)
{
  // SOLO si los parametros son validos
  ASSERT(hdc);
  ASSERT(swDeciPt);

  // Configura el DC recibido  
  SetGraphicsMode(hdc, GM_ADVANCED);
  ModifyWorldTransform(hdc, NULL, MWT_IDENTITY);
  SetViewportOrgEx(hdc, 0, 0, NULL);
  SetWindowOrgEx(hdc, 0, 0, NULL);

  // Se establece la res. logica
  float cxDpi = (float) GetDeviceCaps(hdc, LOGPIXELSX);
  float cyDpi = (float) GetDeviceCaps(hdc, LOGPIXELSY);

  // Define ptos. por pulgada
  POINT pt;
  pt.x = 0;
  pt.y = (sword) (swDeciPt * cyDpi / 72);
  DPtoLP(hdc, &pt, 1);

  // Configura y crea la fuente
  LOGFONT lf;
  memset(&lf, 0, sizeof(lf));
  lf.lfHeight = -(sword) (fabs(pt.y) / 10.0 + 0.5);
  strcpy(lf.lfFaceName, m_FontInfo.szName.c_str());
  m_FontInfo.hFont = CreateFontIndirect(&lf);
  lf.lfQuality = ANTIALIASED_QUALITY;

  // Se obtiene datos sobre metrica y anchura
  m_FontInfo.hPrevFont = (HFONT) SelectObject(hdc, m_FontInfo.hFont);
  GetTextMetrics(hdc, &m_FontInfo.tm);
  GetCharABCWidths(hdc, 32, 255, m_FontInfo.abc);

  // Restaura el estado del hdc anterior  
}
Ejemplo n.º 5
0
CommonFontInfo GetFontInfoSys(Font font)
{
	CommonFontInfo fi;
	memset(&fi, 0, sizeof(fi));
	HFONT hfont = GetWin32Font(font, 0);
	if(hfont) {
		HDC hdc = Win32_IC();
		HFONT ohfont = (HFONT) ::SelectObject(hdc, hfont);
		TEXTMETRIC tm;
		::GetTextMetrics(hdc, &tm);
		fi.ascent = tm.tmAscent;
		fi.descent = tm.tmDescent;
		fi.external = tm.tmExternalLeading;
		fi.internal = tm.tmInternalLeading;
		fi.height = fi.ascent + fi.descent;
		fi.lineheight = fi.height + fi.external;
		fi.overhang = tm.tmOverhang;
		fi.avewidth = tm.tmAveCharWidth;
		fi.maxwidth = tm.tmMaxCharWidth;
		fi.firstchar = tm.tmFirstChar;
		fi.charcount = tm.tmLastChar - tm.tmFirstChar + 1;
		fi.default_char = tm.tmDefaultChar;
		fi.fixedpitch = (tm.tmPitchAndFamily & TMPF_FIXED_PITCH) == 0;
		fi.ttf = fi.scaleable = tm.tmPitchAndFamily & TMPF_TRUETYPE;
		if(fi.scaleable) {
			ABC abc;
			GetCharABCWidths(hdc, 'o', 'o', &abc);
			fi.spacebefore = abc.abcA;
			fi.spaceafter = abc.abcC;
		}
		else
			fi.spacebefore = fi.spaceafter = 0;
		::SelectObject(hdc, ohfont);
	}
	return fi;
}
Ejemplo n.º 6
0
ALERROR CG16bitFont::CreateFromFont (HFONT hFont)

//	CreatFromFont
//
//	Creates from a GDI font

	{
	ALERROR error;
	HDC hDC = CreateCompatibleDC(NULL);
	HFONT hOldFont = (HFONT)SelectObject(hDC, hFont);
	HBITMAP hTempBmp = NULL;
	HBITMAP hFontBmp = NULL;
	HBITMAP hOldBitmap;
	int i, y;

	//	Get some metrics. For some reason we need to recreate the DC after
	//	the GetTextMetrics or else the fonts won't be anti-aliased!

	TEXTMETRIC tm;
	GetTextMetrics(hDC, &tm);

	SelectObject(hDC, hOldFont);
	DeleteDC(hDC);

	hDC = CreateCompatibleDC(NULL);

	//	Remember some for the whole font metrics

	m_Metrics.RemoveAll();
	m_cyHeight = tm.tmHeight;
	m_cyAscent = tm.tmAscent;
	m_cxAveWidth = tm.tmAveCharWidth;

	//	Create a bitmap that will contain all the font characters

	if (error = dibCreate16bitDIB(tm.tmMaxCharWidth, tm.tmHeight * g_iCharCount, &hFontBmp, NULL))
		goto Fail;

	//	Prepare the DC

	hOldBitmap = (HBITMAP)SelectObject(hDC, hFontBmp);
	hOldFont = (HFONT)SelectObject(hDC, hFont);
	SetTextColor(hDC, RGB(255,255,255));
	SetBkColor(hDC, RGB(0,0,0));
	SetBkMode(hDC, TRANSPARENT);

	//	Get the name of the font that we selected

	char szFontName[256];
	::GetTextFace(hDC, sizeof(szFontName), szFontName);
	m_sTypeface = CString(szFontName);

	//	Write each font character to the bitmap

	y = 0;
	for (i = 0; i < g_iCharCount; i++)
		{
		char chChar = (char)(g_iStartChar + i);

		//	Blt

		TextOut(hDC, 0, y, &chChar, 1);

		//	Remember some metrics

		CharMetrics Metrics;
		ABC abc;
		GetCharABCWidths(hDC, (BYTE)chChar, (BYTE)chChar, &abc);
		Metrics.cxWidth = abc.abcA + abc.abcB;
		Metrics.cxAdvance = abc.abcA + abc.abcB + abc.abcC;
		if (error = m_Metrics.AppendStruct(&Metrics, NULL))
			goto Fail;

#ifdef MOREDEBUG
		kernelDebugLogMessage("char: %d  width: %d  advance: %d", (int)chChar, Metrics.cxWidth, Metrics.cxAdvance);
#endif

		//	Next

		y += m_cyHeight;
		}

	SelectObject(hDC, hOldBitmap);

	//	Now apply the bitmap to our image

	if (error = m_FontImage.CreateFromBitmap(NULL, hFontBmp, CG16bitImage::cfbDesaturateAlpha))
		goto Fail;

	//	Done

	DeleteObject(hFontBmp);
	SelectObject(hDC, hOldFont);
	DeleteDC(hDC);

	return NOERROR;

Fail:

	if (hFontBmp)
		{
		SelectObject(hDC, hOldBitmap);
		DeleteObject(hFontBmp);
		}

	SelectObject(hDC, hOldFont);
	DeleteDC(hDC);
	return error;
	}
Ejemplo n.º 7
0
bool CFont::Init()
{
  HDC hDC = CreateCompatibleDC(0);
  int iXdpi, iYdpi;
  iXdpi = GetDeviceCaps(hDC, LOGPIXELSX);
  iYdpi = GetDeviceCaps(hDC, LOGPIXELSY);

  LOGFONT lf;
  lf.lfHeight = m_iSizePt * iYdpi / 72;
  lf.lfWidth = 0;
  lf.lfEscapement = 0;
  lf.lfOrientation = 0;
  lf.lfWeight = FW_DONTCARE;
  lf.lfItalic = false;
  lf.lfUnderline = false;
  lf.lfStrikeOut = false;
  lf.lfCharSet = ANSI_CHARSET;
  lf.lfOutPrecision = OUT_TT_PRECIS;
  lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  lf.lfQuality = ANTIALIASED_QUALITY;
  lf.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
  strcpy(lf.lfFaceName, m_sTypeface.m_pBuf);

  HFONT hFont = CreateFontIndirect(&lf);
  SelectObject(hDC, hFont);

  TEXTMETRIC tm;
  bool bRes;
  bRes = !!GetTextMetrics(hDC, &tm);
  m_iAscent = tm.tmAscent;
  m_iDescent = tm.tmDescent;
  m_iHeight = tm.tmHeight;
  m_iInternalLead = tm.tmInternalLeading;
  m_iExternalLead = tm.tmExternalLeading;
  m_iAverageWidth = tm.tmAveCharWidth;
//  m_iMaxWidth = tm.tmMaxCharWidth;
  m_iFirstChar = tm.tmFirstChar;

  int iChars = tm.tmLastChar - tm.tmFirstChar + 1;
  float fCols, fRows;

  ABC abc[MAX_CHARS];
  bRes = !!GetCharABCWidths(hDC, tm.tmFirstChar, tm.tmLastChar, abc + tm.tmFirstChar);

  int i;
  m_iMaxWidth = 0;
  for (i = 0; i < tm.tmFirstChar; i++)
    m_Chars[i].ch = 0;
  while (i <= tm.tmLastChar) {
    m_Chars[i].ch = i;
    m_Chars[i].iA = abc[i].abcA;
    m_Chars[i].iB = abc[i].abcB;
    m_Chars[i].iC = abc[i].abcC;
    m_iMaxWidth = Util::Max(m_iMaxWidth, m_Chars[i].iB);
    i++;
  }
  while (i < MAX_CHARS) {
    m_Chars[i].ch = 0;
    i++;
  }

  int iKernPairs;
  KERNINGPAIR *pKernPairs;
  iKernPairs = GetKerningPairs(hDC, 0, 0);
  pKernPairs = new KERNINGPAIR[iKernPairs];
  GetKerningPairs(hDC, iKernPairs, pKernPairs);

  for (i = 0; i < iKernPairs; i++) 
    m_KerningPairs.Add(TKerningPair((char) pKernPairs[i].wFirst, (char) pKernPairs[i].wSecond, pKernPairs[i].iKernAmount));

  delete [] pKernPairs;

  fRows = sqrt(iChars * m_iMaxWidth / (float) m_iHeight);
  fCols = fRows * m_iHeight / (float) m_iMaxWidth;
  m_iCellCols = (int) ceil(fCols);
  m_iCellRows = (int) ceil(fRows);

  if (m_iCellCols > m_iCellRows) {
    if (m_iCellCols * (m_iCellRows - 1) >= iChars)
      m_iCellRows--;
  } else
    if ((m_iCellCols - 1) * m_iCellRows >= iChars) 
      m_iCellCols--;

  ASSERT(m_iCellRows * m_iCellCols >= iChars);

  BITMAPINFO bmi;
  bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
  bmi.bmiHeader.biWidth = m_iCellCols * m_iMaxWidth; 
  bmi.bmiHeader.biHeight = -m_iCellRows * m_iHeight; 
  bmi.bmiHeader.biPlanes = 1; 
  bmi.bmiHeader.biBitCount = 24; 
  bmi.bmiHeader.biCompression = BI_RGB; 
  bmi.bmiHeader.biSizeImage = 0; 
  bmi.bmiHeader.biXPelsPerMeter = (int) (iXdpi / 2.54f * 100); 
  bmi.bmiHeader.biYPelsPerMeter = (int) (iYdpi / 2.54f * 100); 
  bmi.bmiHeader.biClrUsed = 0; 
  bmi.bmiHeader.biClrImportant = 0; 

  HBITMAP hBmp = CreateDIBSection(hDC, &bmi, 0, 0, 0, 0);
  SelectObject(hDC, hBmp);

  HBRUSH hBrush = CreateSolidBrush(RGB(0, 0, 0)); 
  SelectObject(hDC, hBrush);

  Rectangle(hDC, 0, 0, m_iCellCols * m_iMaxWidth, m_iCellRows * m_iHeight);

  SetTextColor(hDC, RGB(255, 255, 255));
  SetBkColor(hDC, RGB(0, 0, 0));
  SetBkMode(hDC, TRANSPARENT);
  SetTextAlign(hDC, TA_TOP | TA_LEFT | TA_NOUPDATECP);

  for (int iRow = 0; iRow < m_iCellRows; iRow++)
    for (int iCol = 0; iCol < m_iCellCols; iCol++) {
      RECT rc;
      char chBuf[2] = { m_iFirstChar + iRow * m_iCellCols + iCol, 0 };
      if (!m_Chars[(uint8_t) chBuf[0]].ch)
        continue;
      rc.left = iCol * m_iMaxWidth - m_Chars[(uint8_t) chBuf[0]].iA;
      rc.top = iRow * m_iHeight;
      rc.right = rc.left + m_iMaxWidth;
      rc.bottom = rc.top + m_iHeight;
//      DrawText(hDC, chBuf, 1, &rc, DT_LEFT | DT_TOP);
      TextOut(hDC, rc.left, rc.top, chBuf, 1);
    }

  bRes = !!GdiFlush();

  bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
  bmi.bmiHeader.biWidth = m_iCellCols * m_iMaxWidth; 
  bmi.bmiHeader.biHeight = -m_iCellRows * m_iHeight; 
  bmi.bmiHeader.biPlanes = 1; 
  bmi.bmiHeader.biBitCount = 32; 
  bmi.bmiHeader.biCompression = BI_RGB; 
  bmi.bmiHeader.biSizeImage = 0; 
  bmi.bmiHeader.biXPelsPerMeter = (int) (iXdpi / 2.54f * 100); 
  bmi.bmiHeader.biYPelsPerMeter = (int) (iYdpi / 2.54f * 100); 
  bmi.bmiHeader.biClrUsed = 0; 
  bmi.bmiHeader.biClrImportant = 0; 
  int iSize = bmi.bmiHeader.biWidth * abs(bmi.bmiHeader.biHeight) * bmi.bmiHeader.biBitCount / 8;
  uint8_t *pBuf = new uint8_t[iSize];
  bRes = !!GetDIBits(hDC, hBmp, 0, abs(bmi.bmiHeader.biHeight), pBuf, &bmi, DIB_RGB_COLORS);

  for (i = 0; i < iSize; i += 4)
//    Util::Swap(pBuf[i], pBuf[i + 2]);
    pBuf[i / 4] = pBuf[i];

  m_pTexture = new CTexture();
  bRes = m_pTexture->Init(bmi.bmiHeader.biWidth, abs(bmi.bmiHeader.biHeight), DXGI_FORMAT_R8_UNORM, 1, pBuf, bmi.bmiHeader.biWidth /* * bmi.bmiHeader.biBitCount / 8*/, 0);

/*
  ID3D11Resource *pTexRes = 0;
  m_pTexture->m_pTextureView->GetResource(&pTexRes);
  D3DX11SaveTextureToFile(CGraphics::Get()->m_pDeviceContext, pTexRes, D3DX11_IFF_BMP, "font.bmp");
  SAFE_RELEASE(pTexRes);
*/

  delete [] pBuf;
  DeleteObject(hBrush);
  DeleteObject(hBmp);
  DeleteObject(hFont);
  DeleteDC(hDC);

  if (!InitModel())
    return false;

  return true;
}
Ejemplo n.º 8
0
void AppMain()
{
    int textureSize = 1024;
    int weight      = 0;
    bool italic     = false;
    bool underline  = false;
    char *fontName   = "kremlin";
    char *backupName = "arial";



    // dont edit any more

    g_windowManager = new WindowManager();
    g_windowManager->CreateWin( textureSize, textureSize, true, 32, 60, 32, "FontExtract" );        
    HDC dc = g_windowManager->m_win32Specific->m_hDC;
    int charSize = textureSize / 16;

    HFONT theFont = CreateFont( charSize, 0, 0, 0, 
                                weight, 
                                italic, 
                                underline, false, 
                                DEFAULT_CHARSET,
                                OUT_DEFAULT_PRECIS,
                                CLIP_DEFAULT_PRECIS,
                                NONANTIALIASED_QUALITY,
                                FIXED_PITCH,
                                fontName );

    HFONT backupFont = CreateFont( charSize, 0, 0, 0, 
                                   weight,
                                   italic,
                                   underline, false,
                                   DEFAULT_CHARSET,
                                   OUT_DEFAULT_PRECIS,
                                   CLIP_DEFAULT_PRECIS,
                                   ANTIALIASED_QUALITY,
                                   FIXED_PITCH,
                                   backupName );

    SetTextColor( dc, RGB(255,255,255) );
    SetBkColor( dc, RGB(0,0,0) );

    RECT fillRect;
    fillRect.left = 0;
    fillRect.right = textureSize;
    fillRect.top = 0;
    fillRect.bottom = textureSize;

    FillRect( dc, &fillRect, (HBRUSH)GetStockObject(BLACK_BRUSH) );

    while( true )
    {   
        HGDIOBJ prevObj = SelectObject( dc, theFont );

        //
        // Main font

        for( int i = 0; i < 256; ++i )
        {
            int xPos = (i % 16);
            int yPos = (i / 16);
        
            char caption[32];
            sprintf( caption, "%c", i );
            
            RECT drawRect;
            drawRect.top = yPos * charSize;
            drawRect.bottom = yPos * charSize + charSize;
            drawRect.left = xPos * charSize;
            drawRect.right = xPos * charSize + charSize;
        
            int result = DrawText( dc,
                                   caption, -1,
                                   &drawRect,
                                   DT_CENTER );

            ABC abcs[1];
            GetCharABCWidths( dc, i, i, abcs );

            if( abcs[0].abcB == 1 )
            {
                SelectObject( dc, backupFont );
                int result = DrawText( dc,
                                       caption, -1,
                                       &drawRect,
                                       DT_CENTER );
                SelectObject( dc, theFont );
            }
        }
        

        SelectObject(dc, prevObj);
        
        g_windowManager->PollForMessages();           
    }
       
}
Ejemplo n.º 9
0
bool osd_font_windows::get_bitmap(unicode_char chnum, bitmap_argb32 &bitmap, INT32 &width, INT32 &xoffs, INT32 &yoffs)
{
    // create a dummy DC to work with
    HDC dummyDC = CreateCompatibleDC(NULL);
    HGDIOBJ oldfont = SelectObject(dummyDC, m_font);

    // get the text metrics
    TEXTMETRIC metrics = { 0 };
    GetTextMetrics(dummyDC, &metrics);

    // get the width of this character
    ABC abc;
    if (!GetCharABCWidths(dummyDC, chnum, chnum, &abc))
    {
        abc.abcA = 0;
        abc.abcC = 0;
        GetCharWidth32(dummyDC, chnum, chnum, reinterpret_cast<LPINT>(&abc.abcB));
    }
    width = abc.abcA + abc.abcB + abc.abcC;

    // determine desired bitmap size
    int bmwidth = (50 + abc.abcA + abc.abcB + abc.abcC + 50 + 31) & ~31;
    int bmheight = 50 + metrics.tmHeight + 50;

    // describe the bitmap we want
    BYTE bitmapinfodata[sizeof(BITMAPINFOHEADER)+2 * sizeof(RGBQUAD)] = { 0 };
    BITMAPINFO &info = *reinterpret_cast<BITMAPINFO *>(bitmapinfodata);
    info.bmiHeader.biSize = sizeof(info.bmiHeader);
    info.bmiHeader.biWidth = bmwidth;
    info.bmiHeader.biHeight = -bmheight;
    info.bmiHeader.biPlanes = 1;
    info.bmiHeader.biBitCount = 1;
    info.bmiHeader.biCompression = BI_RGB;
    info.bmiHeader.biSizeImage = 0;
    info.bmiHeader.biXPelsPerMeter = GetDeviceCaps(dummyDC, HORZRES) / GetDeviceCaps(dummyDC, HORZSIZE);
    info.bmiHeader.biYPelsPerMeter = GetDeviceCaps(dummyDC, VERTRES) / GetDeviceCaps(dummyDC, VERTSIZE);
    info.bmiHeader.biClrUsed = 0;
    info.bmiHeader.biClrImportant = 0;
    RGBQUAD col1 = info.bmiColors[0];
    RGBQUAD col2 = info.bmiColors[1];
    col1.rgbBlue = col1.rgbGreen = col1.rgbRed = 0x00;
    col2.rgbBlue = col2.rgbGreen = col2.rgbRed = 0xff;

    // create a DIB to render to
    BYTE *bits;
    HBITMAP dib = CreateDIBSection(dummyDC, &info, DIB_RGB_COLORS, reinterpret_cast<VOID **>(&bits), NULL, 0);

    if (dib)
    {
        HGDIOBJ oldbitmap = SelectObject(dummyDC, dib);

        // clear the bitmap
        int rowbytes = bmwidth / 8;
        memset(bits, 0, rowbytes * bmheight);

        // now draw the character
        WCHAR tempchar = chnum;
        SetTextColor(dummyDC, RGB(0xff, 0xff, 0xff));
        SetBkColor(dummyDC, RGB(0x00, 0x00, 0x00));
        ExtTextOutW(dummyDC, 50 + abc.abcA, 50, ETO_OPAQUE, NULL, &tempchar, 1, NULL);

        // characters are expected to be full-height
        rectangle actbounds;
        actbounds.min_y = 50;
        actbounds.max_y = 50 + metrics.tmHeight - 1;

        // determine the actual left of the character
        for (actbounds.min_x = 0; actbounds.min_x < rowbytes; actbounds.min_x++)
        {
            BYTE *offs = bits + actbounds.min_x;
            UINT8 summary = 0;
            for (int y = 0; y < bmheight; y++)
                summary |= offs[y * rowbytes];
            if (summary != 0)
            {
                actbounds.min_x *= 8;
                if (!(summary & 0x80)) actbounds.min_x++;
                if (!(summary & 0xc0)) actbounds.min_x++;
                if (!(summary & 0xe0)) actbounds.min_x++;
                if (!(summary & 0xf0)) actbounds.min_x++;
                if (!(summary & 0xf8)) actbounds.min_x++;
                if (!(summary & 0xfc)) actbounds.min_x++;
                if (!(summary & 0xfe)) actbounds.min_x++;
                break;
            }
        }

        // determine the actual right of the character
        for (actbounds.max_x = rowbytes - 1; actbounds.max_x >= 0; actbounds.max_x--)
        {
            BYTE *offs = bits + actbounds.max_x;
            UINT8 summary = 0;
            for (int y = 0; y < bmheight; y++)
                summary |= offs[y * rowbytes];
            if (summary != 0)
            {
                actbounds.max_x *= 8;
                if (summary & 0x7f) actbounds.max_x++;
                if (summary & 0x3f) actbounds.max_x++;
                if (summary & 0x1f) actbounds.max_x++;
                if (summary & 0x0f) actbounds.max_x++;
                if (summary & 0x07) actbounds.max_x++;
                if (summary & 0x03) actbounds.max_x++;
                if (summary & 0x01) actbounds.max_x++;
                break;
            }
        }

        // allocate a new bitmap
        if (actbounds.max_x >= actbounds.min_x && actbounds.max_y >= actbounds.min_y)
        {
            bitmap.allocate(actbounds.max_x + 1 - actbounds.min_x, actbounds.max_y + 1 - actbounds.min_y);

            // copy the bits into it
            for (int y = 0; y < bitmap.height(); y++)
            {
                UINT32 *dstrow = &bitmap.pix32(y);
                UINT8 *srcrow = &bits[(y + actbounds.min_y) * rowbytes];
                for (int x = 0; x < bitmap.width(); x++)
                {
                    int effx = x + actbounds.min_x;
                    dstrow[x] = ((srcrow[effx / 8] << (effx % 8)) & 0x80) ? rgb_t(0xff, 0xff, 0xff, 0xff) : rgb_t(0x00, 0xff, 0xff, 0xff);
                }
            }

            // set the final offset values
            xoffs = actbounds.min_x - (50 + abc.abcA);
            yoffs = actbounds.max_y - (50 + metrics.tmAscent);
        }

        // de-select the font and release the DC
        SelectObject(dummyDC, oldbitmap);
        DeleteObject(dib);
    }

    SelectObject(dummyDC, oldfont);
    DeleteDC(dummyDC);
    return bitmap.valid();
}
Ejemplo n.º 10
0
CDrawContext::FontInfo * CDrawContext::GetFont( const FontDef &fdef )
//
//	Create a font. If the font already exists in our map of fonts then we use that
//	if the font does not exist then we create it.
{
	FontInfo **ppInfo = m_mapFonts.Lookup( fdef );
	if( ppInfo )
	{
		return (*ppInfo);
	}

	LOGFONT lf = {0};
	(void)_tcscpy( lf.lfFaceName, fdef.m_szFontName );
	lf.lfWeight = fdef.m_nWeight;
	lf.lfHeight = fdef.m_nSizePixels;
	lf.lfItalic = fdef.m_bItalic;
	lf.lfUnderline = fdef.m_bUnderline;
	lf.lfStrikeOut = fdef.m_bStrike;
	lf.lfQuality = DRAFT_QUALITY;
	lf.lfCharSet = fdef.m_cCharSet;
	lf.lfOutPrecision = OUT_TT_ONLY_PRECIS;

	FontInfo *pInfo = new FontInfo;
	pInfo->hFont = CreateFontIndirect( &lf );


	//
	//	Get and store the widths of the individual characters, these are used
	//	later when calculating the lengths of text in pixels.
	HGDIOBJ hFontOld = ::SelectObject( m_hdc, pInfo->hFont );

	//
	//	Store some extra bits and pieces.
	TEXTMETRIC tm;
	GetTextMetrics( m_hdc, &tm );
	pInfo->m_nBaseline = tm.tmAscent;
	pInfo->m_nLineSpace = tm.tmHeight + tm.tmExternalLeading;
	if( fdef.m_bUnderline )
		pInfo->m_nLineSpace++;

	ABC abcWids[ countof( pInfo->m_nWidths ) ];
	memset( abcWids, 0, sizeof( abcWids ) );
	if( GetCharABCWidths( m_hdc, 0, countof( pInfo->m_nWidths ) - 1, abcWids ) )
	{
		ABC *pABC = &abcWids[0];
		int *parrWidths = pInfo->m_nWidths;
		if( tm.tmOverhang )
		{
			int *parrOverhang = pInfo->m_nOverhang;

			for( UINT n = 0; n < countof( pInfo->m_nWidths ) ; n++, pABC++ )
			{
				*parrWidths++ = ( pABC->abcA + pABC->abcB + pABC->abcC );
				*parrOverhang++ = pABC->abcC;
			}
		}
		else
		{
			for( UINT n = 0; n < countof( pInfo->m_nWidths ) ; n++, pABC++ )
			{
				*parrWidths++ = ( pABC->abcA + pABC->abcB + pABC->abcC );
			}
			memset( pInfo->m_nOverhang, 0, sizeof( pInfo->m_nOverhang ) );
		}
	}
	else
	{
		int *parrWidths = pInfo->m_nWidths;
		if( !GetCharWidth32( m_hdc, 0, 255, parrWidths ) )
		{
			SIZE size;
			TCHAR ch = 0;
			for( UINT n = 0; n < 255; n++ )
			{
				ch = (TCHAR)n;
				GetTextExtentPoint32( m_hdc, &ch, 1, &size );
				*parrWidths++ = size.cx;
			}
		}
		memset( pInfo->m_nOverhang, 0, sizeof( pInfo->m_nOverhang ) );
	}

	::SelectObject( m_hdc, hFontOld );

	//
	//	And finally add the font to our cache.
	if( pInfo->hFont )
		m_arrObjToDelete.Add( pInfo->hFont );
	m_mapFonts.SetAt( fdef, pInfo );

	return pInfo;
}
Ejemplo n.º 11
0
void CWin32Font::GetCharRGBA(int ch, int rgbaX, int rgbaY, int rgbaWide, int rgbaTall, unsigned char *rgba)
{
	int a, b, c;
	GetCharABCWidths(ch, a, b, c);
	::SelectObject(m_hDC, m_hFont);

	int wide = b;

	if (m_bUnderlined)
		wide += (a + c);

	int tall = m_iHeight;
	GLYPHMETRICS glyphMetrics;
	MAT2 mat2 = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };
	int bytesNeeded = 0;

	bool bShouldAntialias = m_bAntiAliased;

	if (ch > 0x00FF && !(m_iFlags & vgui::ISurface::FONTFLAG_CUSTOM))
		bShouldAntialias = false;

	if (!s_bSupportsUnicode)
	{
		if (ch == 'I' || ch == '1')
			bShouldAntialias = false;

		if (m_iHeight >= 13)
			bShouldAntialias = false;
	}

	if (bShouldAntialias)
	{
		::SelectObject(m_hDC, m_hFont);
		bytesNeeded = ::GetGlyphOutlineW(m_hDC, ch, GGO_GRAY8_BITMAP, &glyphMetrics, 0, NULL, &mat2);
	}

	if (bytesNeeded > 0)
	{
		unsigned char *lpbuf = (unsigned char *)_alloca(bytesNeeded);
		::GetGlyphOutlineW(m_hDC, ch, GGO_GRAY8_BITMAP, &glyphMetrics, bytesNeeded, lpbuf, &mat2);

		wide = glyphMetrics.gmBlackBoxX;

		while (wide % 4 != 0)
			wide++;

		int pushDown = m_iAscent - glyphMetrics.gmptGlyphOrigin.y;
		int xstart = 0;

		if ((int)glyphMetrics.gmBlackBoxX >= b + 2)
			xstart = (glyphMetrics.gmBlackBoxX - b) / 2;

		for (unsigned int j = 0; j < glyphMetrics.gmBlackBoxY; j++)
		{
			for (unsigned int i = xstart; i < glyphMetrics.gmBlackBoxX; i++)
			{
				int x = i - xstart + m_iBlur + m_iOutlineSize;
				int y = j + pushDown;

				if ((x < rgbaWide) && (y < rgbaTall))
				{
					unsigned char grayscale = lpbuf[(j * wide + i)];
					float r, g, b, a;

					if (grayscale)
					{
						r = g = b = 1.0f;
						a = (grayscale + 0) / 64.0f;
						if (a > 1.0f) a = 1.0f;
					}
					else
						r = g = b = a = 0.0f;

					if (ch == '\t')
						r = g = b = 0;

					unsigned char *dst = &rgba[(y*rgbaWide+x)*4];
					dst[0] = (unsigned char)(r * 255.0f);
					dst[1] = (unsigned char)(g * 255.0f);
					dst[2] = (unsigned char)(b * 255.0f);
					dst[3] = (unsigned char)(a * 255.0f);
				}
			}
		}
	}
	else
	{
		::SetBkColor(m_hDC, RGB(0, 0, 0));
		::SetTextColor(m_hDC, RGB(255, 255, 255));
		::SetBkMode(m_hDC, OPAQUE);

		if (m_bUnderlined)
			::MoveToEx(m_hDC, 0, 0, NULL);
		else
			::MoveToEx(m_hDC, -a, 0, NULL);

		wchar_t wch = (wchar_t)ch;

		if (s_bSupportsUnicode)
		{
			::ExtTextOutW(m_hDC, 0, 0, 0, NULL, &wch, 1, NULL);
		}
		else
		{
			RECT rect = { 0, 0, wide, tall};
			::ExtTextOut(m_hDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);

			char mbcs[6] = { 0 };
			::WideCharToMultiByte(CP_ACP, 0, &wch, 1, mbcs, sizeof(mbcs), NULL, NULL);
			::ExtTextOutA(m_hDC, 0, 0, 0, NULL, mbcs, strlen(mbcs), NULL);
		}

		::SetBkMode(m_hDC, TRANSPARENT);

		if (wide > m_rgiBitmapSize[0])
			wide = m_rgiBitmapSize[0];

		if (tall > m_rgiBitmapSize[1])
			tall = m_rgiBitmapSize[1];

		for (int j = (int)m_iOutlineSize; j < tall - (int)m_iOutlineSize; j++)
		{
			for (int i = (int)m_iOutlineSize; i < wide - (int)m_iDropShadowOffset - (int)m_iOutlineSize; i++)
			{
				if ((i < rgbaWide) && (j < rgbaTall))
				{
					unsigned char *src = &m_pBuf[(i + j*m_rgiBitmapSize[0])*4];
					unsigned char *dst = &rgba[(i + j*rgbaWide)*4];
					unsigned char r, g, b;

					if (ch == '\t')
					{
						r = g = b = 0;
					}
					else
					{
						r = src[0];
						g = src[1];
						b = src[2];
					}

					dst[0] = r;
					dst[1] = g;
					dst[2] = b;
					dst[3] = (unsigned char)((float)r * 0.34f + (float)g * 0.55f + (float)b * 0.11f);
				}
			}
		}

		if (m_iDropShadowOffset)
		{
			unsigned char *dst = &rgba[((m_iHeight - 1) * rgbaWide) * 4];

			for (int i = 0; i < wide; i++)
			{
				dst[0] = 0;
				dst[1] = 0;
				dst[2] = 0;
				dst[3] = 0;
				dst += 4;
			}
		}
	}

	if (m_iDropShadowOffset)
		ApplyDropShadowToTexture(rgbaX, rgbaY, rgbaWide, rgbaTall, wide, tall, rgba);

	if (m_iOutlineSize)
		ApplyOutlineToTexture(rgbaX, rgbaY, rgbaWide, rgbaTall, wide, tall, rgba);

	ApplyGaussianBlurToTexture(rgbaX, rgbaY, rgbaWide, rgbaTall, rgba);
	ApplyScanlineEffectToTexture(rgbaX, rgbaY, rgbaWide, rgbaTall, rgba);
	ApplyRotaryEffectToTexture(rgbaX, rgbaY, rgbaWide, rgbaTall, rgba);
}
Ejemplo n.º 12
0
//-----------------------------------------------------------------------------
// Purpose: writes the char into the specified 32bpp texture
//-----------------------------------------------------------------------------
void CWin32Font::GetCharRGBA(wchar_t ch, int rgbaWide, int rgbaTall, unsigned char *rgba)
{
	int a, b, c;
	GetCharABCWidths(ch, a, b, c);

	// set us up to render into our dib
	::SelectObject(m_hDC, m_hFont);

	int wide = b;
	if ( m_bUnderlined )
	{
		wide += ( a + c );
	}

	int tall = m_iHeight;
	GLYPHMETRICS glyphMetrics;
	MAT2 mat2 = { { 0, 1}, { 0, 0}, { 0, 0}, { 0, 1}};
	int bytesNeeded = 0;

	bool bShouldAntialias = m_bAntiAliased;
	// filter out 
	if ( ch > 0x00FF && !(m_iFlags & vgui::ISurface::FONTFLAG_CUSTOM) )
	{
		bShouldAntialias = false;
	}
	if ( !s_bSupportsUnicode )
	{
		// win98 hack, don't antialias some characters that ::GetGlyphOutline() produces bad results for
		if (ch == 'I' || ch == '1')
		{
			bShouldAntialias = false;
		}

		// don't antialias big fonts at all (since win98 often produces bad results)
		if (m_iHeight >= 13)
		{
			bShouldAntialias = false;
		}
	}


	// only antialias latin characters, since it essentially always fails for asian characters
	if (bShouldAntialias)
	{
		// try and get the glyph directly
		::SelectObject(m_hDC, m_hFont);
		bytesNeeded = ::GetGlyphOutline(m_hDC, ch, GGO_GRAY8_BITMAP, &glyphMetrics, 0, NULL, &mat2);
	}

	if (bytesNeeded > 0)
	{
		// take it
		unsigned char *lpbuf = (unsigned char *)_alloca(bytesNeeded);
		::GetGlyphOutline(m_hDC, ch, GGO_GRAY8_BITMAP, &glyphMetrics, bytesNeeded, lpbuf, &mat2);

		// rows are on DWORD boundaries
		wide = glyphMetrics.gmBlackBoxX;
		while (wide % 4 != 0)
		{
			wide++;
		}

		// see where we should start rendering
		int pushDown = m_iAscent - glyphMetrics.gmptGlyphOrigin.y;

		// set where we start copying from
		int xstart = 0;

		// don't copy the first set of pixels if the antialiased bmp is bigger than the char width
		if ((int)glyphMetrics.gmBlackBoxX >= b + 2)
		{
			xstart = (glyphMetrics.gmBlackBoxX - b) / 2;
		}

		// iterate through copying the generated dib into the texture
		for (unsigned int j = 0; j < glyphMetrics.gmBlackBoxY; j++)
		{
			for (unsigned int i = xstart; i < glyphMetrics.gmBlackBoxX; i++)
			{
				int x = i - xstart + m_iBlur + m_iOutlineSize;
				int y = j + pushDown;
				if ((x < rgbaWide) && (y < rgbaTall))
				{
					unsigned char grayscale = lpbuf[(j*wide+i)];

					float r, g, b, a;
					if (grayscale)
					{
						r = g = b = 1.0f;
						a = (grayscale + 0) / 64.0f;
						if (a > 1.0f) a = 1.0f;
					}
					else
					{
						r = g = b = a = 0.0f;
					}

					// Don't want anything drawn for tab characters.
					if (ch == '\t')
					{
						r = g = b = 0;
					}

					unsigned char *dst = &rgba[(y*rgbaWide+x)*4];
					dst[0] = (unsigned char)(r * 255.0f);
					dst[1] = (unsigned char)(g * 255.0f);
					dst[2] = (unsigned char)(b * 255.0f);
					dst[3] = (unsigned char)(a * 255.0f);
				}
			}
		}
	}
	else
	{
		// use render-to-bitmap to get our font texture
		::SetBkColor(m_hDC, RGB(0, 0, 0));
		::SetTextColor(m_hDC, RGB(255, 255, 255));
		::SetBkMode(m_hDC, OPAQUE);
		if ( m_bUnderlined )
		{
			::MoveToEx(m_hDC, 0, 0, NULL);
		}
		else
		{
			::MoveToEx(m_hDC, -a, 0, NULL);
		}

		// render the character
		wchar_t wch = (wchar_t)ch;
		
		if (s_bSupportsUnicode)
		{
			// just use the unicode renderer
			::ExtTextOutW(m_hDC, 0, 0, 0, NULL, &wch, 1, NULL);
		}
		else
		{
			// clear the background first (it may not get done automatically in win98/ME
			RECT rect = { 0, 0, wide, tall};
			::ExtTextOut(m_hDC, 0, 0, ETO_OPAQUE, &rect, NULL, 0, NULL);

			// convert the character using the current codepage
			char mbcs[6] = { 0 };
			::WideCharToMultiByte(CP_ACP, 0, &wch, 1, mbcs, sizeof(mbcs), NULL, NULL);
			::ExtTextOutA(m_hDC, 0, 0, 0, NULL, mbcs, strlen(mbcs), NULL);
		}

		::SetBkMode(m_hDC, TRANSPARENT);

		if (wide > m_rgiBitmapSize[0])
		{
			wide = m_rgiBitmapSize[0];
		}
		if (tall > m_rgiBitmapSize[1])
		{
			tall = m_rgiBitmapSize[1];
		}

		// iterate through copying the generated dib into the texture
		for (int j = (int)m_iOutlineSize; j < tall - (int)m_iOutlineSize; j++ )
		{
			// only copy from within the dib, ignore the outline border we are artificially adding
			for (int i = (int)m_iOutlineSize; i < wide - (int)m_iDropShadowOffset - (int)m_iOutlineSize; i++)
			{
				if ((i < rgbaWide) && (j < rgbaTall))
				{
					unsigned char *src = &m_pBuf[(i + j*m_rgiBitmapSize[0])*4];
					unsigned char *dst = &rgba[(i + j*rgbaWide)*4];

					// Don't want anything drawn for tab characters.
					unsigned char r, g, b;
					if ( ch == '\t' )
					{
						r = g = b = 0;
					}
					else
					{
						r = src[0];
						g = src[1];
						b = src[2];
					}

					// generate alpha based on luminance conversion
					dst[0] = r;
					dst[1] = g;
					dst[2] = b;
					dst[3] = (unsigned char)((float)r * 0.34f + (float)g * 0.55f + (float)b * 0.11f);
				}
			}
		}

		// if we have a dropshadow, we need to clean off the bottom row of pixels
		// this is because of a bug in winME that writes noise to them, only on the first time the game is run after a reboot
		// the bottom row should guaranteed to be empty to fit the dropshadow
		if ( m_iDropShadowOffset )
		{
			unsigned char *dst = &rgba[((m_iHeight - 1) * rgbaWide) * 4];
			for (int i = 0; i < wide; i++)
			{
				dst[0] = 0;
				dst[1] = 0;
				dst[2] = 0;
				dst[3] = 0;
				dst += 4;
			}
		}
	}

	// apply requested effects in specified order
	ApplyDropShadowToTexture( rgbaWide, rgbaTall, rgba, m_iDropShadowOffset );
	ApplyOutlineToTexture( rgbaWide, rgbaTall, rgba, m_iOutlineSize );
	ApplyGaussianBlurToTexture( rgbaWide, rgbaTall, rgba, m_iBlur );
	ApplyScanlineEffectToTexture( rgbaWide, rgbaTall, rgba, m_iScanLines );
	ApplyRotaryEffectToTexture( rgbaWide, rgbaTall, rgba, m_bRotary );
}
Ejemplo n.º 13
0
gxFont *gxGraphics::loadFont( const string &f,int height,int flags ){

	int bold=flags & gxFont::FONT_BOLD ? FW_BOLD : FW_REGULAR;
	int italic=flags & gxFont::FONT_ITALIC ? 1 : 0;
	int underline=flags & gxFont::FONT_UNDERLINE ? 1 : 0;
	int strikeout=0;

	string t;
	int n=f.find('.');
	if( n!=string::npos ){
		t=fullfilename(f);
		if( !font_res.count(t) && AddFontResource( t.c_str() ) ) font_res.insert( t );
		t=filenamefile( f.substr(0,n) );
	}else{
		t=f;
	}

	//save and turn off font smoothing....
	BOOL smoothing=FALSE;
	SystemParametersInfo( SPI_GETFONTSMOOTHING,0,&smoothing,0 );
	SystemParametersInfo( SPI_SETFONTSMOOTHING,FALSE,0,0 );

	HFONT hfont=CreateFont( 
		height,0,0,0,
		bold,italic,underline,strikeout,
		ANSI_CHARSET,OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,DEFAULT_QUALITY,
		DEFAULT_PITCH|FF_DONTCARE,t.c_str() );

	if( !hfont ){
		//restore font smoothing
		SystemParametersInfo( SPI_SETFONTSMOOTHING,smoothing,0,0 );
		return 0;
	}

	HDC hdc=CreateCompatibleDC( 0 );
	HFONT pfont=(HFONT)SelectObject( hdc,hfont );

	TEXTMETRIC tm={0};
	if( !GetTextMetrics( hdc,&tm ) ){
		SelectObject( hdc,pfont );
		DeleteDC( hdc );
		DeleteObject( hfont );
		SystemParametersInfo( SPI_SETFONTSMOOTHING,smoothing,0,0 );
		return 0;
	}
	height=tm.tmHeight;

	int first=tm.tmFirstChar,last=tm.tmLastChar;
	int sz=last-first+1;
	int *offs=d_new int[sz];
	int *widths=d_new int[sz];
	int *as=d_new int[sz];

	//calc size of canvas to hold font.
	int x=0,y=0,max_x=0;
	for( int k=0;k<sz;++k ){

		char t=k+first;

		SIZE sz;
		GetTextExtentPoint32( hdc,&t,1,&sz );
		int w=sz.cx;

		as[k]=0;

		ABC abc;
		if( GetCharABCWidths( hdc,t,t,&abc ) ){
			if( abc.abcA<0 ){
				as[k]=ceil(-abc.abcA);
				w+=as[k];
			}
			if( abc.abcC<0 ) w+=ceil(-abc.abcC);
		}

		if( x && x+w>getWidth() ){ x=0;y+=height; }
		offs[k]=(x<<16)|y;
		widths[k]=w;
		x+=w;if( x>max_x ) max_x=x;
	}
	SelectObject( hdc,pfont );
	DeleteDC( hdc );

	int cw=max_x,ch=y+height;

	if( gxCanvas *c=createCanvas( cw,ch,0 ) ){
		ddSurf *surf=c->getSurface();

		HDC surf_hdc;
		if( surf->GetDC( &surf_hdc )>=0 ){
			HFONT pfont=(HFONT)SelectObject( surf_hdc,hfont );

			SetBkColor( surf_hdc,0x000000 );
			SetTextColor( surf_hdc,0xffffff );

			for( int k=0;k<sz;++k ){
				int x=(offs[k]>>16)&0xffff,y=offs[k]&0xffff;
				char t=k+first;
				RECT rect={x,y,x+widths[k],y+height};
				ExtTextOut( surf_hdc,x+as[k],y,ETO_CLIPPED,&rect,&t,1,0 );
			}

			SelectObject( surf_hdc,pfont );
			surf->ReleaseDC( surf_hdc );
			DeleteObject( hfont );
			delete[] as;

			c->backup();
			gxFont *font=d_new gxFont( this,c,tm.tmMaxCharWidth,height,first,last+1,tm.tmDefaultChar,offs,widths );
			font_set.insert( font );

			//restore font smoothing
			SystemParametersInfo( SPI_SETFONTSMOOTHING,smoothing,0,0 );
			return font;
		}else{