예제 #1
0
	int InitGlyph(wchar_t ch)
	{
		DWORD len,i,ii,j,k,t;
		BYTE *buffer,*bptr;
		LPVOID ptr;
		MAT2 mt={};
		glyph_char=ch;
		mt.eM11.value=1;
		mt.eM22.value=-1;
		len=GetGlyphOutline(hDC,ch,GGO_GRAY8_BITMAP,&gm,0,0,&mt);
		if (len==-1) return -1;
		glyph_buffer=new BYTE[len];
		len=GetGlyphOutline(hDC,ch,GGO_GRAY8_BITMAP,&gm,len,glyph_buffer,&mt);
		if (len==-1) return -1;	
		BITMAPINFOHEADER info={sizeof(info),gm.gmBlackBoxX,gm.gmBlackBoxY,1,32,BI_RGB,0,0,0,0,0};
		hBmp=CreateDIBSection(hMemDC,(BITMAPINFO*)&info,DIB_RGB_COLORS,&ptr,0,0);
		buffer=(BYTE*)ptr;
		bptr=glyph_buffer;
		k=(gm.gmBlackBoxX+3)&~3;t=0;ii=0;
		for (i=0;i<gm.gmBlackBoxY;i++)
		{
			for (j=0;j<gm.gmBlackBoxX;j++)
			{
				bptr[j]=64-bptr[j];
				if (bptr[j]) 
					buffer[0]=buffer[1]=buffer[2]=(bptr[j]<<2)-1;
				buffer+=4;
			}
			bptr+=k;
		}
		SelectObject(hMemDC,hBmp);
		return 0;
	}
예제 #2
0
파일: bitmapfont.c 프로젝트: hbao/LCUI
test()
{
        MAT2 glyph_mat = {{0,1},{0,0},{0,0},{0,1}};
        int buff_len;
        GLYPHMETRICS glyph_metrics;
        unsigned char *buff;
        buff_len = GetGlyphOutline( NULL, L'a', GGO_BITMAP, &glyph_metrics, 0, NULL, &glyph_mat );
        GetGlyphOutline( NULL, L'a', GGO_BITMAP, &glyph_metrics, buff_len, buff, &glyph_mat);
}
예제 #3
0
파일: XFont.cpp 프로젝트: g200kg/SkinMan
GraphicsPath *XGraphicsPath::GetCharGlyph(HDC hdc,UINT chr,PointF ptfOffset) {
	GLYPHMETRICS gm;
	BYTE *buff;
	TTPOLYGONHEADER *phdr;
	TTPOLYCURVE *pcur;
	PointF ptf[4],ptfLast;
	int i,j,n,iTotalBytes,iTotalBytesCount,iPolygonBytes,iPolygonBytesCount;
	const MAT2 m={{0,1},{0,0},{0,0},{0,1}};
	GraphicsPath *path=new GraphicsPath();
	iTotalBytes=GetGlyphOutline(hdc, chr,GGO_BEZIER|GGO_UNHINTED,&gm,0,NULL,&m);
	if(iTotalBytes==0||iTotalBytes==GDI_ERROR)
		return path;
	buff=new BYTE[iTotalBytes];
	iTotalBytesCount=0;
	GetGlyphOutline(hdc,chr,GGO_BEZIER|GGO_UNHINTED,&gm,iTotalBytes,buff,&m);
	phdr=(TTPOLYGONHEADER*)buff;
	while(iTotalBytesCount<iTotalBytes) {
		ptfLast=PointFx2PointF(phdr->pfxStart,ptfOffset);
		iPolygonBytes=phdr->cb;
		iPolygonBytesCount=sizeof(TTPOLYGONHEADER);
		pcur=(TTPOLYCURVE*)(phdr+1);
		while(iPolygonBytesCount<iPolygonBytes) {
			n=pcur->cpfx;
			switch(pcur->wType) {
			case TT_PRIM_QSPLINE:
				break;
			case TT_PRIM_CSPLINE:
				for(j=0;j<n;j+=3) {
					ptf[0]=ptfLast;
					for(i=0;i<3;++i)
						ptf[i+1]=PointFx2PointF(pcur->apfx[j+i],ptfOffset);
					path->AddBezier(ptf[0],ptf[1],ptf[2],ptf[3]);
					ptfLast=ptf[3];
				}
				break;
			case TT_PRIM_LINE:
				for(j=0;j<n;++j) {
					ptf[0]=PointFx2PointF(pcur->apfx[j],ptfOffset);
					path->AddLine(ptfLast,ptf[0]);
					ptfLast=ptf[0];
				}
				break;
			}
			iPolygonBytesCount+=sizeof(POINTFX)*n+4;
			pcur=(TTPOLYCURVE*)((char*)pcur+sizeof(POINTFX)*n+4);
		}
		path->CloseFigure();
		iTotalBytesCount+=iPolygonBytes;
		phdr=(TTPOLYGONHEADER*)((char*)phdr+iPolygonBytes);
	}
	delete[] buff;
	return path;
}
예제 #4
0
short CRenderEngine::CalcOffsety(HDC hDc)
{
	MAT2 mat2 = {{0,1}, {0,0}, {0,0}, {0,1}};
	GLYPHMETRICS gm={0};
	if(GetGlyphOutline(hDc,_T('j'),GGO_GRAY8_BITMAP,&gm,0,NULL,&mat2)!=GDI_ERROR)
	{
		short y=gm.gmBlackBoxY;
		if(GetGlyphOutline(hDc,_T('b'),GGO_GRAY8_BITMAP,&gm,0,NULL,&mat2)!=GDI_ERROR)
		{
			return (y-gm.gmBlackBoxY);
		}
	}

	return 0;
}
예제 #5
0
void Font::initGDIFont()
{
    if (!m_platformData.size()) {
        m_fontMetrics.reset();
        m_avgCharWidth = 0;
        m_maxCharWidth = 0;
        return;
    }

    HWndDC hdc(0);
    HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());
    OUTLINETEXTMETRIC metrics;
    GetOutlineTextMetrics(hdc, sizeof(metrics), &metrics);
    TEXTMETRIC& textMetrics = metrics.otmTextMetrics;
    float ascent = textMetrics.tmAscent;
    float descent = textMetrics.tmDescent;
    float lineGap = textMetrics.tmExternalLeading;
    m_fontMetrics.setAscent(ascent);
    m_fontMetrics.setDescent(descent);
    m_fontMetrics.setLineGap(lineGap);
    m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
    m_avgCharWidth = textMetrics.tmAveCharWidth;
    m_maxCharWidth = textMetrics.tmMaxCharWidth;
    float xHeight = ascent * 0.56f; // Best guess for xHeight if no x glyph is present.
    GLYPHMETRICS gm;
    static const MAT2 identity = { 0, 1,  0, 0,  0, 0,  0, 1 };
    DWORD len = GetGlyphOutline(hdc, 'x', GGO_METRICS, &gm, 0, 0, &identity);
    if (len != GDI_ERROR && gm.gmptGlyphOrigin.y > 0)
        xHeight = gm.gmptGlyphOrigin.y;
    m_fontMetrics.setXHeight(xHeight);
    m_fontMetrics.setUnitsPerEm(metrics.otmEMSquare);

    SelectObject(hdc, oldFont);
}
예제 #6
0
 static int getGlyphWidth (HDC dc, int glyphNumber)
 {
     GLYPHMETRICS gm;
     gm.gmCellIncX = 0;
     GetGlyphOutline (dc, (UINT) glyphNumber, GGO_NATIVE | GGO_GLYPH_INDEX, &gm, 0, 0, &identityMatrix);
     return gm.gmCellIncX;
 }
예제 #7
0
파일: truetype.cpp 프로젝트: 2asoft/xray
BOOL TrueTypeImport::BuildCharacter(UINT index, float height, BezierShape &shape, float &width, int fontShapeVersion) {
    assert(hFont);
	if(!hFont)
		return 0;

	// Set up for the font and release it when this function returns
	FontReady fontRdy(hFont);
			    
	// allocate space for the bitmap/outline
	GLYPHMETRICS gm;
    // init it to prevent UMR in GetGlyphOutline
    gm.gmBlackBoxX = 
    gm.gmBlackBoxY = 
    gm.gmptGlyphOrigin.x =
    gm.gmptGlyphOrigin.y =
    gm.gmCellIncX = 
    gm.gmCellIncY = 0; 

	// Give it an identity matrix
	MAT2 mat;
	IdentityMat(&mat);

	DWORD size = GetGlyphOutline(fontRdy.hdc, index, GGO_NATIVE, &gm, 0, NULL, &mat);
	if(size != GDI_ERROR && size > 0) {
		GenericAlloc mem(size);
		if(!mem.ptr)
			goto failure;
		if ((GetGlyphOutline(fontRdy.hdc, index, GGO_NATIVE, &gm, size, mem.ptr, &mat)) != size)
			goto failure;
		curSpline = NULL;	// reset the current spline pointer
		if(!CreateCharacterShape((TTPOLYGONHEADER *)mem.ptr, size, shape, fontShapeVersion))
			goto failure;
		// Make sure the height matches the request
		float scaleFactor = height / 1000.0f;
		Matrix3 tm = ScaleMatrix(Point3(scaleFactor, scaleFactor, 0.0f));
		shape.Transform(tm);
		width = float(gm.gmCellIncX) * scaleFactor;
		return TRUE;
		}

	// Character wasn't found!
	failure:
	width = 0.0f;
	return FALSE;
	}
예제 #8
0
SIZE CRenderEngine::GetDrawSize(HDC hDc,LPTSTR lpszText,UINT uFormat,bool& bHaveOffsety,short& yOffset)
{
	SIZE size={0,0};
	if(lpszText==NULL)
		return size;

	long slen=_tcslen(lpszText);
	if(slen==0)
		return size;

	MAT2 mat2 = {{0,1}, {0,0}, {0,0}, {0,1}};
	GLYPHMETRICS gm={0};
	UINT nChar;
	for(int n=0; n<slen; n++)
	{
		nChar=*(lpszText+n);
		//·ÇÓ¢ÎÄ
		if(nChar >= 0xa0)
		{
			nChar = (((nChar<<8)&0xff00) | (*(lpszText+ ++n) & 0x00ff)); 
		}
		if(GetGlyphOutline(hDc,nChar,GGO_GRAY8_BITMAP,&gm,0,NULL,&mat2)!=GDI_ERROR)
		{
			size.cx+=gm.gmBlackBoxX+m_cxSpacing;
			size.cy=max(size.cy,gm.gmBlackBoxY);
		}
		if(nChar == _T(' '))
		{
			size.cx+=m_cwBlank;
		}
		else
		{
			switch(nChar)
			{
			case _T('j'):
			case _T('J'):
			case _T('y'):
			case _T('g'):
				bHaveOffsety=true;
				break;
			}
		}
	}

	if(bHaveOffsety)
	{
		yOffset=CalcOffsety(hDc);
		size.cy+=yOffset;
	}
	else
		yOffset=0;

	return size;
}
예제 #9
0
void SimpleFontData::platformInit()
{
    m_scriptCache = 0;
    m_scriptFontProperties = 0;
    m_isSystemFont = false;

    m_syntheticBoldOffset = m_platformData.syntheticBold() ? 1.0f : 0.f;

    if (m_platformData.useGDI())
       return initGDIFont();

    HDC hdc = GetDC(0);
    SaveDC(hdc);

    cairo_scaled_font_t* scaledFont = m_platformData.scaledFont();
    const double metricsMultiplier = cairo_win32_scaled_font_get_metrics_factor(scaledFont) * m_platformData.size();

    cairo_win32_scaled_font_select_font(scaledFont, hdc);

    TEXTMETRIC textMetrics;
    GetTextMetrics(hdc, &textMetrics);
    float ascent = textMetrics.tmAscent * metricsMultiplier;
    float descent = textMetrics.tmDescent * metricsMultiplier;
    float xHeight = ascent * 0.56f; // Best guess for xHeight for non-Truetype fonts.
    float lineGap = textMetrics.tmExternalLeading * metricsMultiplier;
    m_fontMetrics.setAscent(ascent);
    m_fontMetrics.setDescent(descent);
    m_fontMetrics.setLineGap(lineGap);
    m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
    m_avgCharWidth = textMetrics.tmAveCharWidth * metricsMultiplier;
    m_maxCharWidth = textMetrics.tmMaxCharWidth * metricsMultiplier;

    OUTLINETEXTMETRIC metrics;
    if (GetOutlineTextMetrics(hdc, sizeof(metrics), &metrics) > 0) {
        // This is a TrueType font.  We might be able to get an accurate xHeight
        GLYPHMETRICS gm;
        MAT2 mat = { 1, 0, 0, 1 };
        DWORD len = GetGlyphOutline(hdc, 'x', GGO_METRICS, &gm, 0, 0, &mat);
        if (len != GDI_ERROR && gm.gmptGlyphOrigin.y > 0)
            xHeight = gm.gmptGlyphOrigin.y * metricsMultiplier;
    }

    m_fontMetrics.setXHeight(xHeight);
    cairo_win32_scaled_font_done_font(scaledFont);

    m_isSystemFont = false;
    m_scriptCache = 0;
    m_scriptFontProperties = 0;

    RestoreDC(hdc, -1);
    ReleaseDC(0, hdc);
}
예제 #10
0
int CChildView::GetStringWidth(CString strong)
{
	int width=0;
	CFont    ThisFont;
	CFont*   pOldFont;
	GLYPHMETRICS gm;
	DWORD res;
	MAT2 m2 = {{0, 1}, {0, 0}, {0, 0}, {0, 1}}; 
	CPaintDC dc(this); // device context for painting
	HDC hDC = dc.m_hDC;

	ThisFont.CreateFontIndirect(&m_WndLogFont);
	pOldFont = dc.SelectObject(&ThisFont);
	res = GetGlyphOutline(hDC,32,GGO_BITMAP,&gm,32,NULL, &m2);

	for (int l=0; l<strong.GetLength(); l++){
		res = dc.GetGlyphOutline(strong[l], 0, &gm, 0, NULL, &m2);
		res = GetGlyphOutline(hDC,strong[l],GGO_BITMAP,&gm,32,NULL, &m2);
		width += (int)(gm.gmBlackBoxX);
	}
	dc.SelectObject(pOldFont);
	return max(width,0);
}
예제 #11
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;
}
FloatRect SimpleFontData::platformBoundsForGlyph(Glyph glyph) const
{
    HWndDC hdc(0);
    SetGraphicsMode(hdc, GM_ADVANCED);
    HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());

    GLYPHMETRICS gdiMetrics;
    static const MAT2 identity = { 0, 1,  0, 0,  0, 0,  0, 1 };
    if (GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity) == -1) {
        if (FontPlatformData::ensureFontLoaded(m_platformData.hfont())) {
            // Retry GetTextMetrics.
            // FIXME: Handle gracefully the error if this call also fails.
            // See http://crbug.com/6401.
            if (GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity) == -1)
                LOG_ERROR("Unable to get the glyph metrics after second attempt");
        }
    }

    SelectObject(hdc, oldFont);

    return FloatRect(gdiMetrics.gmptGlyphOrigin.x, -gdiMetrics.gmptGlyphOrigin.y,
        gdiMetrics.gmBlackBoxX, gdiMetrics.gmBlackBoxY);
}
예제 #13
0
/*------------------------------------------------------------------------------*
| <<< アンチエイリアスフォントのピクセル情報を得る >>>
|	入力	iID    = 管理番号
|			uiCode = 文字コード
|	戻り値	false  = 文字を得られなかった
*------------------------------------------------------------------------------*/
static	bool	AFontPixelGet(int iID, uint uiCode, TEXTMETRIC *tm)
{

	AFONT_WORK	*a = &afont[iID];

	//--- ビットマップ取得 ------------------------------------------
	MAT2	m   = {{0, 1}, {0, 0}, {0, 0}, {0, 1}};
	uint	fmt = GGO_GRAY8_BITMAP;			// ほかに GGO_GRAY2_BITMAP、GGO_GRAY4_BITMAP がある

	//--- アンチフォントを取り出す ----------------------------------
	HDC		hDc = d3.font[a->cFontNum]->GetDC();

	int	iSize = GetGlyphOutline(hDc, uiCode, fmt, &a->gmAnt, 0, NULL, &m);
	if(iSize == 0){ return false;}
	GetGlyphOutline(hDc, uiCode, fmt, &a->gmAnt, iSize, a->pBuf, &m);
	GetTextMetrics( hDc, tm);

	//--- 文字の横幅を決める ----------------------------------------
	int		iW = d3.fontInfo[a->cFontNum].Width;
	int		iH = d3.fontInfo[a->cFontNum].Height;
	if(uiCode >= 0x100){ iW *= 2;}			// 全角ならば横幅は二倍になる

	return true;
}
예제 #14
0
FloatRect Font::boundsForGDIGlyph(Glyph glyph) const
{
    HWndDC hdc(0);
    SetGraphicsMode(hdc, GM_ADVANCED);
    HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());

    GLYPHMETRICS gdiMetrics;
    static const MAT2 identity = { 0, 1,  0, 0,  0, 0,  0, 1 };
    GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity);

    SelectObject(hdc, oldFont);

    return FloatRect(gdiMetrics.gmptGlyphOrigin.x, -gdiMetrics.gmptGlyphOrigin.y,
        gdiMetrics.gmBlackBoxX + m_syntheticBoldOffset, gdiMetrics.gmBlackBoxY); 
}
예제 #15
0
float Font::widthForGDIGlyph(Glyph glyph) const
{
    HWndDC hdc(0);
    SetGraphicsMode(hdc, GM_ADVANCED);
    HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());

    GLYPHMETRICS gdiMetrics;
    static const MAT2 identity = { 0, 1,  0, 0,  0, 0,  0, 1 };
    GetGlyphOutline(hdc, glyph, GGO_METRICS | GGO_GLYPH_INDEX, &gdiMetrics, 0, 0, &identity);
    float result = gdiMetrics.gmCellIncX + m_syntheticBoldOffset;

    SelectObject(hdc, oldFont);

    return result;
}
예제 #16
0
void Font::initGDIFont()
{
    if (!m_platformData.size()) {
        m_fontMetrics.reset();
        m_avgCharWidth = 0;
        m_maxCharWidth = 0;
        return;
    }

    HWndDC hdc(0);
    HGDIOBJ oldFont = SelectObject(hdc, m_platformData.hfont());
    OUTLINETEXTMETRIC metrics;
    GetOutlineTextMetrics(hdc, sizeof(metrics), &metrics);
    TEXTMETRIC& textMetrics = metrics.otmTextMetrics;
    float ascent, descent, lineGap;
    // The Open Font Format describes the OS/2 USE_TYPO_METRICS flag as follows:
    // "If set, it is strongly recommended to use OS/2.sTypoAscender - OS/2.sTypoDescender+ OS/2.sTypoLineGap as a value for default line spacing for this font."
    const UINT useTypoMetricsMask = 1 << 7;
    if (metrics.otmfsSelection & useTypoMetricsMask) {
        ascent = metrics.otmAscent;
        descent = metrics.otmDescent;
        lineGap = metrics.otmLineGap;
    } else {
        ascent = textMetrics.tmAscent;
        descent = textMetrics.tmDescent;
        lineGap = textMetrics.tmExternalLeading;
    }
    m_fontMetrics.setAscent(ascent);
    m_fontMetrics.setDescent(descent);
    m_fontMetrics.setLineGap(lineGap);
    m_fontMetrics.setLineSpacing(lroundf(ascent) + lroundf(descent) + lroundf(lineGap));
    m_avgCharWidth = textMetrics.tmAveCharWidth;
    m_maxCharWidth = textMetrics.tmMaxCharWidth;
    float xHeight = ascent * 0.56f; // Best guess for xHeight if no x glyph is present.
    GLYPHMETRICS gm;
    static const MAT2 identity = { 0, 1,  0, 0,  0, 0,  0, 1 };
    DWORD len = GetGlyphOutline(hdc, 'x', GGO_METRICS, &gm, 0, 0, &identity);
    if (len != GDI_ERROR && gm.gmptGlyphOrigin.y > 0)
        xHeight = gm.gmptGlyphOrigin.y;
    m_fontMetrics.setXHeight(xHeight);
    m_fontMetrics.setUnitsPerEm(metrics.otmEMSquare);

    SelectObject(hdc, oldFont);
}
예제 #17
0
파일: HUD.cpp 프로젝트: ousttrue/dscvd3d
    void Update()
    {
        if(m_text==m_ss.str()){
            return;
        }

        m_text=m_ss.str();

        m_image->Clear();
        BYTE *data=m_image->GetSample();
        int pitch=m_image->GetWidth()*4;

        // フォントの生成
        LOGFONT lf = {m_fontsize, 0, 0, 0, 0, 0, 0, 0, 
            SHIFTJIS_CHARSET, OUT_TT_ONLY_PRECIS,
            CLIP_DEFAULT_PRECIS, PROOF_QUALITY, FIXED_PITCH | FF_MODERN, _T("MS 明朝")};
        HFONT hFont=CreateFontIndirect(&lf);
        if(!(hFont)){
            return;
        }

        // デバイスコンテキスト取得
        // デバイスにフォントを持たせないとGetGlyphOutline関数はエラーとなる
        HDC hdc = GetDC(NULL);
        HFONT oldFont = (HFONT)SelectObject(hdc, hFont);

        std::vector<BYTE> gryph;
        int x_pos=0;
        int y_pos=0;
        int col_size=m_fontsize/2;
        for(auto c=m_text.begin(); c!=m_text.end(); ++c){

            if(y_pos>=m_row*m_fontsize){
                break;
            }

            if(*c==L'\n'){
                y_pos+=m_fontsize+5;
                x_pos=0;
                continue;
            }

            if(x_pos+col_size>=m_col*col_size){
                y_pos+=m_fontsize+5;
                x_pos=0;
            }

            // フォントビットマップ取得
            TEXTMETRIC TM;
            GetTextMetrics( hdc, &TM );
            GLYPHMETRICS GM;
            CONST MAT2 Mat = {{0,1},{0,0},{0,0},{0,1}};
            DWORD size = GetGlyphOutline(hdc, *c, GGO_GRAY4_BITMAP, &GM, 0, NULL, &Mat);

            if(size>0){
                gryph.resize(size);
                GetGlyphOutline(hdc, *c, GGO_GRAY4_BITMAP, &GM, gryph.size(), &gryph[0], &Mat);

                // フォント情報の書き込み
                // iOfs_x, iOfs_y : 書き出し位置(左上)
                // iBmp_w, iBmp_h : フォントビットマップの幅高
                // Level : α値の段階 (GGO_GRAY4_BITMAPなので17段階)
                int iOfs_x = x_pos+GM.gmptGlyphOrigin.x;
                int iOfs_y = y_pos+TM.tmAscent - GM.gmptGlyphOrigin.y;
                int iBmp_w = GM.gmBlackBoxX + (4-(GM.gmBlackBoxX%4))%4;
                int iBmp_h = GM.gmBlackBoxY;
                int Level = 17;
                DWORD Alpha, Color;
                for(int y=iOfs_y; y<iOfs_y+iBmp_h; y++){
                    for(size_t x=iOfs_x; x<iOfs_x+GM.gmBlackBoxX; x++){
                        Alpha = (255 * gryph[x-iOfs_x + iBmp_w*(y-iOfs_y)]) / (Level-1);
                        Color = 0x00ffffff | (Alpha<<24);
                        memcpy((BYTE*)data + pitch*y + 4*x, &Color, sizeof(DWORD));
                    }
                }
                x_pos+=iBmp_w;
            }
            else{
                x_pos+=col_size;
            }
        }

        // デバイスコンテキストとフォントハンドルの開放
        SelectObject(hdc, oldFont);
        DeleteObject(hFont);
        ReleaseDC(NULL, hdc);
    }
예제 #18
0
WINGDIAPI BOOL GLAPIENTRY wglUseFontBitmapsA(HDC hdc, DWORD first,
					     DWORD count, DWORD listBase)
{
    int i;
    GLuint font_list;
    DWORD size;
    GLYPHMETRICS gm;
    HANDLE hBits;
    LPSTR lpBits;
    MAT2 mat;
    int  success = TRUE;
    
    if (count == 0)
	return FALSE;
    
    font_list = listBase;
    
    mat.eM11 = FixedFromDouble(1);
    mat.eM12 = FixedFromDouble(0);
    mat.eM21 = FixedFromDouble(0);
    mat.eM22 = FixedFromDouble(-1);
    
    memset(&gm,0,sizeof(gm));
    
    /*
    ** If we can't get the glyph outline, it may be because this is a fixed
    ** font.  Try processing it that way.
    */
    if( GetGlyphOutline(hdc, first, GGO_BITMAP, &gm, 0, NULL, &mat)
	== GDI_ERROR ) {
	return wglUseFontBitmaps_FX( hdc, first, count, listBase );
    }
    
    /*
    ** Otherwise process all desired characters.
    */
    for (i = 0; i < (int)count; i++) {
	DWORD err;
	
	glNewList( font_list+i, GL_COMPILE );
	
	/* allocate space for the bitmap/outline */
	size = GetGlyphOutline(hdc, first + i, GGO_BITMAP, 
			       &gm, 0, NULL, &mat);
	if (size == GDI_ERROR) {
	    glEndList( );
	    err = GetLastError();
	    success = FALSE;
	    continue;
	}
	
	hBits  = GlobalAlloc(GHND, size+1);
	lpBits = GlobalLock(hBits);
	
	err = 
	    GetGlyphOutline(hdc,         /* handle to device context */
			    first + i,   /* character to query */
			    GGO_BITMAP,  /* format of data to return */
			    &gm,         /* ptr to structure for metrics*/
			    size,        /* size of buffer for data */
			    lpBits,      /* pointer to buffer for data */
			    &mat         /* pointer to transformation */
			    /* matrix structure */
		);
	
	if (err == GDI_ERROR) {
	    GlobalUnlock(hBits);
	    GlobalFree(hBits);
	    
	    glEndList( );
	    err = GetLastError();
	    success = FALSE;
	    continue;
	}
	
	glBitmap(gm.gmBlackBoxX,gm.gmBlackBoxY,
		 (GLfloat)-gm.gmptGlyphOrigin.x,
		 (GLfloat)gm.gmptGlyphOrigin.y,
		 (GLfloat)gm.gmCellIncX,
		 (GLfloat)gm.gmCellIncY,
		 (const GLubyte * )lpBits);
	
	GlobalUnlock(hBits);
	GlobalFree(hBits);
	
	glEndList( );
    }
    
    return success;
}
예제 #19
0
    bool getOutlineForGlyph (int glyphNumber, Path& glyphPath)
    {
        if (glyphNumber < 0)
            glyphNumber = defaultGlyph;

        GLYPHMETRICS gm;
        // (although GetGlyphOutline returns a DWORD, it may be -1 on failure, so treat it as signed int..)
        const int bufSize = (int) GetGlyphOutline (dc, (UINT) glyphNumber, GGO_NATIVE | GGO_GLYPH_INDEX,
                                                   &gm, 0, 0, &identityMatrix);

        if (bufSize > 0)
        {
            HeapBlock<char> data (bufSize);
            GetGlyphOutline (dc, (UINT) glyphNumber, GGO_NATIVE | GGO_GLYPH_INDEX, &gm,
                             bufSize, data, &identityMatrix);

            const TTPOLYGONHEADER* pheader = reinterpret_cast<TTPOLYGONHEADER*> (data.getData());

            const float scaleX = 1.0f / tm.tmHeight;
            const float scaleY = -scaleX;

            while ((char*) pheader < data + bufSize)
            {
                glyphPath.startNewSubPath (scaleX * pheader->pfxStart.x.value,
                                           scaleY * pheader->pfxStart.y.value);

                const TTPOLYCURVE* curve = (const TTPOLYCURVE*) ((const char*) pheader + sizeof (TTPOLYGONHEADER));
                const char* const curveEnd = ((const char*) pheader) + pheader->cb;

                while ((const char*) curve < curveEnd)
                {
                    if (curve->wType == TT_PRIM_LINE)
                    {
                        for (int i = 0; i < curve->cpfx; ++i)
                            glyphPath.lineTo (scaleX * curve->apfx[i].x.value,
                                              scaleY * curve->apfx[i].y.value);
                    }
                    else if (curve->wType == TT_PRIM_QSPLINE)
                    {
                        for (int i = 0; i < curve->cpfx - 1; ++i)
                        {
                            const float x2 = scaleX * curve->apfx[i].x.value;
                            const float y2 = scaleY * curve->apfx[i].y.value;
                            float x3       = scaleX * curve->apfx[i + 1].x.value;
                            float y3       = scaleY * curve->apfx[i + 1].y.value;

                            if (i < curve->cpfx - 2)
                            {
                                x3 = 0.5f * (x2 + x3);
                                y3 = 0.5f * (y2 + y3);
                            }

                            glyphPath.quadraticTo (x2, y2, x3, y3);
                        }
                    }

                    curve = (const TTPOLYCURVE*) &(curve->apfx [curve->cpfx]);
                }

                pheader = (const TTPOLYGONHEADER*) curve;

                glyphPath.closeSubPath();
            }
        }

        return true;
    }
예제 #20
0
// ****************************************************************************
//
//  Function Name:	RTrueTypeFont::GetGlyphOutline( )
//
//  Description:		
//
//  Returns:			Nothing
//
//  Exceptions:		Memory, Font
//
// ****************************************************************************
//
void RTrueTypeFont::GetGlyphOutline( Handle sfnt, long glyphIndex, GlyphOutline* pOutline, Matrix xform )
{
short 						state = GetFontState( sfnt );
short 						upem, sideBearing, adjustToLsb;
short* 						glyph;
sfnt_FontHeader* 			head;
sfnt_HorizontalHeader*	hhea;
sfnt_HorizontalMetrics*	hori;
long 							length;
long 							longMetrics;

	try
	{
		::HLock( sfnt );
		head = (sfnt_FontHeader *)GetSfntTablePtr( sfnt, tag_FontHeader );
		hhea = (sfnt_HorizontalHeader *)GetSfntTablePtr( sfnt, tag_HoriHeader );
		hori = (sfnt_HorizontalMetrics *)GetSfntTablePtr( sfnt, tag_HorizontalMetrics );
		if ( head == NULL || hhea == NULL || hori == NULL )
			throw fontNotOutlineErr;
	
		upem = head->unitsPerEm;
		longMetrics = hhea->numberLongMetrics;
		if ( glyphIndex < longMetrics )
		{	
			pOutline->advance.x = ::FixRatio( hori[glyphIndex].advance, upem );
			sideBearing = hori[glyphIndex].sideBearing;
		}
		else
		{	
			short *lsb = (short *)&hori[longMetrics]; 		// first entry after[AW,LSB] array 
			pOutline->advance.x = ::FixRatio( hori[longMetrics-1].advance, upem );
			sideBearing = hori[glyphIndex - longMetrics].sideBearing;
		}
		pOutline->advance.y = 0;
	
		pOutline->origin.x = pOutline->origin.y = 0;
	
		if ( (glyph = (short *)GetSfntGlyphPtr(sfnt, glyphIndex, &length)) == 0 )
			throw fontNotOutlineErr;
	
		if ( length == 0 )
		{	
			pOutline->contourCount = pOutline->pointCount = 0;
			SetFontState( sfnt, state );
			return;
		}
	
		pOutline->contourCount = *glyph++;
		adjustToLsb = *glyph - sideBearing;			// xmin - lsb 
		glyph += 4;											// skip bounds rect 
	
		if ( pOutline->contourCount == 0 )
			pOutline->pointCount = 0;
		else if ( pOutline->contourCount == -1 )
		{	
			short	flags, index, newMatrix;
			pOutline->contourCount = pOutline->pointCount = 0;
			mySetHandleSize( (Handle)pOutline->endPoints, 0 );
			mySetHandleSize( (Handle)pOutline->onCurve, 0 );
			mySetHandleSize( (Handle)pOutline->x, 0 );
			mySetHandleSize( (Handle)pOutline->y, 0 );
			do
			{	
				Matrix compXform;
				short arg1, arg2;
				
				flags = *glyph++;
				index = *glyph++;
				newMatrix = false;
	
				if ( flags & ARG_1_AND_2_ARE_WORDS )
				{	
					arg1 = *glyph++;
					arg2 = *glyph++;
				}
				else
				{	
					char* byteP = (char*)glyph;
					if ( flags & ARGS_ARE_XY_VALUES )
					{									// offsets are signed 
						arg1 = *byteP++;
						arg2 = *byteP;
					}
					else
					{									// anchor points are unsigned 
						arg1 = (unsigned char)*byteP++;
						arg2 = (unsigned char)*byteP;
					}
					++glyph;
				}
#if IMPLEMENT_SCALED_COMPONENTS
				if ( flags & (WE_HAVE_A_SCALE | WE_HAVE_AN_X_AND_Y_SCALE | WE_HAVE_A_TWO_BY_TWO) )
				{	
					Matrix subXform;
					MakeIdentityMatrix( subXform );
					if ( flags & WE_HAVE_A_TWO_BY_TWO )
					{	compXform[0][0] = (Fixed)*glyph++ << 2;
						compXform[0][1] = (Fixed)*glyph++ << 2;
						compXform[1][0] = (Fixed)*glyph++ << 2;
						compXform[1][1] = (Fixed)*glyph++ << 2;
					}
					else if ( flags & WE_HAVE_AN_X_AND_Y_SCALE )
					{	compXform[0][0] = (Fixed)*glyph++ << 2;
						compXform[1][1] = (Fixed)*glyph++ << 2;
					}
					else
						compXform[0][0] = compXform[1][1] = (Fixed)*glyph++ << 2;
					PostMulMatrix (compXform, xform );
					newMatrix = true;
				}
#endif			
				{	
					GlyphOutline out;
					InitGlyphOutline( &out );
					GetGlyphOutline( sfnt, index, &out, newMatrix ? compXform : xform );
					{	
						Fixed dx, dy;
						if ( flags & ARGS_ARE_XY_VALUES )
						{	dx = ::FixRatio(arg1, upem);
							dy = -::FixRatio(arg2, upem);
						}
						else
						{	
							dx = (*pOutline->x)[arg1] - (*out.x)[arg2];
							dy = (*pOutline->y)[arg1] - (*out.y)[arg2];
						}
						MoveGlyphOutline( &out, dx, dy );
					}
					AppendGlyphOutline( pOutline, &out );
					KillGlyphOutline( &out );
				}
			} while ( flags & MORE_COMPONENTS );
		}
		else if ( pOutline->contourCount > 0 )
		{																			//	Load in the end points.
			{	
				long size = pOutline->contourCount * sizeof(short);
	
				mySetHandleSize( (Handle)pOutline->endPoints, size );
				BlockMove( (Ptr)glyph, (Ptr)*pOutline->endPoints, size );
				glyph += pOutline->contourCount;
			}
	
			pOutline->pointCount = (*pOutline->endPoints)[pOutline->contourCount - 1] + 1;
			mySetHandleSize( (Handle)pOutline->onCurve, pOutline->pointCount * sizeof(char) );
			mySetHandleSize( (Handle)pOutline->x, pOutline->pointCount * sizeof(Fixed) );
			mySetHandleSize( (Handle)pOutline->y, pOutline->pointCount * sizeof(Fixed) );
	
			//	Skip the word for instruction count + the instructions.
			// Then load in the onCurve bytes.
			{	
				Byte* p = (Byte*)glyph + sizeof(short) + *glyph;
				Byte* onCurve = *pOutline->onCurve;
				Byte* stop = onCurve + pOutline->pointCount;
				Byte flag;
	
				while ( onCurve < stop )
				{	
					*onCurve++ = flag = GetUnsignedByte( p );
					if ( flag & REPEAT_FLAGS ) 
					{
						short count = GetUnsignedByte( p );
						for ( --count; count >= 0; --count )
							*onCurve++ = flag;
					}
				}
				//	Lets do X
				{	
					short coord = adjustToLsb;
					Fixed* x = *pOutline->x;
	
					onCurve = *pOutline->onCurve;
					while ( onCurve < stop )
					{	
						if ( (flag = *onCurve++) & XSHORT ) 
						{
							if ( flag & SHORT_X_IS_POS )
								coord += GetUnsignedByte( p );
							else
								coord -= GetUnsignedByte( p );
						}
						else if ( !(flag & NEXT_X_IS_ZERO) )
						{	
							coord += (short)(*p++) << 8;
							coord += (Byte)*p++;
						}
						*x = ::FixRatio( coord, upem );
						x++;
					}
				}
				//	Lets do Y
				{	
					short coord = 0;
					Fixed* y = *pOutline->y;
	
					onCurve = *pOutline->onCurve;
					while ( onCurve < stop )
					{	
						if ( (flag = *onCurve) & YSHORT ) 
						{
							if ( flag & SHORT_Y_IS_POS )
								coord += GetUnsignedByte( p );
							else
								coord -= GetUnsignedByte( p );
						}
						else if ( !(flag & NEXT_Y_IS_ZERO) )
						{	
							coord += (short)(*p++) << 8;
							coord += (Byte)*p++;
						}
						*y = -::FixRatio( coord, upem );
						y++;
						
						//	Filter off the extra bits
						*onCurve++ = flag & ONCURVE;
					}
				}
			}
		}
		else
			throw fontNotOutlineErr;
	}
	catch ( OSErr osErr )
	{
		SetFontState( sfnt, state );
		switch ( osErr ) 
		{
			case memFullErr :																// out of memeory
				SetFontState( sfnt, state );
				throw kMemory;
				break;
			case fontNotOutlineErr :		 											// bad font
				SetFontState( sfnt, state );
				throw kResource;
				break;
			default:
				TpsAssertAlways( "Bad exception" ); 
				throw;
				break;
		}
	}
	catch ( ... )
	{
		SetFontState( sfnt, state );
		throw;
	}

	SetFontState( sfnt, state );
}
예제 #21
0
// ****************************************************************************
//
//  Function Name:	RTrueTypeFont::ExtractCharacterOutline( )
//
//  Description:		Retrieve a glyph outline and parse it into segment records 
//							in the global buffer
//
//  Returns:			Boolean indicating successful completion
//
//  Exceptions:		Memory
//
// ****************************************************************************
//
BOOLEAN	RTrueTypeFont::ExtractCharacterOutline( int character, uLONG cookie )
{
YTTSegmentInfoRecord*	pSegments = (YTTSegmentInfoRecord *)( cookie + sizeof(uLONG) );
const YFontInfo			fontInfo = GetInfo();
GlyphOutline 				glyph;
Matrix 						matrix;
long 							glyphIndex = 0;					// zero is the missing character

	// retrieve font resource
	if ( m_hSfnt == NULL )
	{
		short		rId;
		ResType	rType;
		Str255	rName;
		m_hSfnt = GetSfntHandle( (const LPSZ)fontInfo.sbName, RFont::GetMacStyleBits( fontInfo.attributes ) );
		GetResInfo( m_hSfnt, &rId, &rType, rName);
		m_sSfntId = rId;
	}
	else if ( *m_hSfnt == NULL )
	{
		::LoadResource( m_hSfnt );
//		m_hSfnt = ::GetResource( 'sfnt', m_sSfntId );
	}
	if ( m_hSfnt == NULL || *m_hSfnt == NULL )
		return FALSE;
	::HNoPurge( m_hSfnt );

	// extract character outline
	InitMatrix( matrix );
	InitGlyphOutline( &glyph );
	MakeIdentityMatrix( matrix );
	try
	{
		glyphIndex = GetCharGlyphIndex( m_hSfnt, character );
		GetGlyphOutline( m_hSfnt, glyphIndex, &glyph, matrix );
		ScaleGlyphOutline( &glyph, ::Long2Fix( fontInfo.height ), ::Long2Fix( fontInfo.height ) );
	}
	catch ( YException except )
	{
		::HPurge( m_hSfnt );
		KillGlyphOutline( &glyph );
		switch ( except ) 
		{
			case kResource:
				return FALSE;
				break;
			default:
				throw;
				break;
		}
	}
	catch ( ... )
	{
		::HPurge( m_hSfnt );
		KillGlyphOutline( &glyph );
		throw;
	}

	// loop thru the contours
	LockGlyphOutline( &glyph );
	{
		long			nrSegments = 0;
		long			sp = 0;
		Fixed*		x = *glyph.x;
		Fixed*		y = *glyph.y;
		short*		ep = *glyph.endPoints;
		Byte*			onCurve = *glyph.onCurve;
		RIntPoint	ptStart;
		for ( int i = 0; i < glyph.contourCount; i++ )
		{	
			long	pts = *ep - sp + 1;													// nr pts in contour
			// contour start point
			if ( *onCurve != 0 )															// 1st point on curve
			{
				ptStart.m_x = RoundFixed( *x );
				ptStart.m_y = -RoundFixed( *y ); 
				x++;
				y++;
				onCurve++;
				pts--;
			}
			else if ( *((*glyph.onCurve) + *ep) != 0 )							// use end point
			{
				ptStart.m_x = RoundFixed( *((*glyph.x) + *ep) );
				ptStart.m_y = -RoundFixed( *((*glyph.y) + *ep) ); 
			}
			else																				// compute midpoint between 1st and last curve points
			{	
				Fixed	x2 = ::FixDiv( (*x + *((*glyph.x) + *ep)), ::Long2Fix( 2 ) );
				Fixed	y2 = ::FixDiv( (*y + *((*glyph.y) + *ep)), ::Long2Fix( 2 ) );
				ptStart.m_x = RoundFixed( x2 );
				ptStart.m_y = -RoundFixed( y2 );
			}
			// initial move to
			pSegments->opCode = MOVE_TO;
			pSegments->pt1 = ptStart;
			nrSegments++;
			pSegments++;
			// load segments of contour
			while ( pts-- > 0 )
			{	
				Fixed	x0 = *x;
				Fixed	y0 = *y;
				Byte	onCurve0 = *onCurve;
				x++;
				y++;
				onCurve++;
				pSegments->pt1.m_x = RoundFixed( x0 );
				pSegments->pt1.m_y = -RoundFixed( y0 );
				if ( onCurve0 != 0 )
					pSegments->opCode = LINE_TO;
				else if ( pts < 1 )														// quadratic w/ contour start point as end
				{
					pSegments->opCode = QUADRATIC_TO;
					pSegments->pt2 = ptStart;
				}
				else if ( *onCurve != 0 )												// quadratic w/ end point next line to
				{
					pSegments->opCode = QUADRATIC_TO;
					pSegments->pt2.m_x = RoundFixed( *x );
					pSegments->pt2.m_y = -RoundFixed( *y );
					x++;
					y++;
					onCurve++;
					pts--;
				}
				else 																			// compute end point of quadratic as midpoint to next curve
				{
					Fixed	x2 = ::FixDiv( (x0 + *x), ::Long2Fix( 2 ) );
					Fixed	y2 = ::FixDiv( (y0 + *y), ::Long2Fix( 2 ) );
					pSegments->opCode = QUADRATIC_TO;
					pSegments->pt2.m_x = RoundFixed( x2 );
					pSegments->pt2.m_y = -RoundFixed( y2 );
				}
				nrSegments++;
				pSegments++;
			}
			pSegments->opCode = CLOSE_PATH;											// end of contour
			pSegments->pt1.m_x = pSegments->pt2.m_x = 0;
			pSegments->pt1.m_y = pSegments->pt2.m_y = 0;
			nrSegments++;
			pSegments++;
			sp = *ep++ + 1;
		}
		pSegments->opCode = 0;															// end of glyph
		pSegments->pt1.m_x = pSegments->pt2.m_x = 0;
		pSegments->pt1.m_y = pSegments->pt2.m_y = 0;
		*(uLONG *)cookie = nrSegments;
	}
	UnlockGlyphOutline( &glyph );

	// cleanup
	::HPurge( m_hSfnt );
	KillGlyphOutline( &glyph );

	return TRUE;
}
예제 #22
0
    bool loadGlyphIfPossible (juce_wchar character)
    {
        HDC dc = FontDCHolder::getInstance()->loadFont (name, isBold, isItalic, 0);

        GLYPHMETRICS gm;

        // if this is the fallback font, skip checking for the glyph's existence. This is because
        // with fonts like Tahoma, GetGlyphIndices can say that a glyph doesn't exist, but it still
        // gets correctly created later on.
        if (! isFallbackFont)
        {
            const WCHAR charToTest[] = { (WCHAR) character, 0 };
            WORD index = 0;

            if (GetGlyphIndices (dc, charToTest, 1, &index, GGI_MARK_NONEXISTING_GLYPHS) != GDI_ERROR
                 && index == 0xffff)
            {
                return false;
            }
        }

        Path glyphPath;

        TEXTMETRIC tm;
        if (! GetTextMetrics (dc, &tm))
        {
            addGlyph (character, glyphPath, 0);
            return true;
        }

        const float height = (float) tm.tmHeight;
        static const MAT2 identityMatrix = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } };

        const int bufSize = GetGlyphOutline (dc, character, GGO_NATIVE,
                                             &gm, 0, 0, &identityMatrix);

        if (bufSize > 0)
        {
            HeapBlock<char> data (bufSize);

            GetGlyphOutline (dc, character, GGO_NATIVE, &gm,
                             bufSize, data, &identityMatrix);

            const TTPOLYGONHEADER* pheader = reinterpret_cast<TTPOLYGONHEADER*> (data.getData());

            const float scaleX = 1.0f / height;
            const float scaleY = -1.0f / height;

            while ((char*) pheader < data + bufSize)
            {
                float x = scaleX * pheader->pfxStart.x.value;
                float y = scaleY * pheader->pfxStart.y.value;

                glyphPath.startNewSubPath (x, y);

                const TTPOLYCURVE* curve = (const TTPOLYCURVE*) ((const char*) pheader + sizeof (TTPOLYGONHEADER));
                const char* const curveEnd = ((const char*) pheader) + pheader->cb;

                while ((const char*) curve < curveEnd)
                {
                    if (curve->wType == TT_PRIM_LINE)
                    {
                        for (int i = 0; i < curve->cpfx; ++i)
                        {
                            x = scaleX * curve->apfx[i].x.value;
                            y = scaleY * curve->apfx[i].y.value;

                            glyphPath.lineTo (x, y);
                        }
                    }
                    else if (curve->wType == TT_PRIM_QSPLINE)
                    {
                        for (int i = 0; i < curve->cpfx - 1; ++i)
                        {
                            const float x2 = scaleX * curve->apfx[i].x.value;
                            const float y2 = scaleY * curve->apfx[i].y.value;
                            float x3, y3;

                            if (i < curve->cpfx - 2)
                            {
                                x3 = 0.5f * (x2 + scaleX * curve->apfx[i + 1].x.value);
                                y3 = 0.5f * (y2 + scaleY * curve->apfx[i + 1].y.value);
                            }
                            else
                            {
                                x3 = scaleX * curve->apfx[i + 1].x.value;
                                y3 = scaleY * curve->apfx[i + 1].y.value;
                            }

                            glyphPath.quadraticTo (x2, y2, x3, y3);

                            x = x3;
                            y = y3;
                        }
                    }

                    curve = (const TTPOLYCURVE*) &(curve->apfx [curve->cpfx]);
                }

                pheader = (const TTPOLYGONHEADER*) curve;

                glyphPath.closeSubPath();
            }
        }

        addGlyph (character, glyphPath, gm.gmCellIncX / height);

        int numKPs;
        const KERNINGPAIR* const kps = FontDCHolder::getInstance()->getKerningPairs (numKPs);

        for (int i = 0; i < numKPs; ++i)
        {
            if (kps[i].wFirst == character)
                addKerningPair (kps[i].wFirst, kps[i].wSecond,
                                kps[i].iKernAmount / height);
        }

        return true;
    }
예제 #23
0
JNIEXPORT jlong JNICALL
Java_sun_font_FileFontStrike__1getGlyphImageFromWindows
(JNIEnv *env, jobject unused,
 jstring fontFamily, jint style, jint size, jint glyphCode, jboolean fm) {

    GLYPHMETRICS glyphMetrics;
    LOGFONTW lf;
    BITMAPINFO bmi;
    TEXTMETRIC textMetric;
    RECT rect;
    int bytesWidth, dibBytesWidth, extra, imageSize, dibImageSize;
    unsigned char* dibImage = NULL, *rowPtr, *pixelPtr, *dibPixPtr, *dibRowPtr;
    unsigned char r,g,b;
    unsigned char* igTable;
    GlyphInfo* glyphInfo = NULL;
    int nameLen;
    LPWSTR name;
    HFONT oldFont, hFont;
    MAT2 mat2;

    unsigned short width;
    unsigned short height;
    short advanceX;
    short advanceY;
    int topLeftX;
    int topLeftY;
    int err;
    int bmWidth, bmHeight;
    int x, y;
    HBITMAP hBitmap = NULL, hOrigBM;
    int gamma, orient;

    HWND hWnd = NULL;
    HDC hDesktopDC = NULL;
    HDC hMemoryDC = NULL;

    hWnd = GetDesktopWindow();
    hDesktopDC = GetWindowDC(hWnd);
    if (hDesktopDC == NULL) {
        return (jlong)0;
    }
    if (GetDeviceCaps(hDesktopDC, BITSPIXEL) < 15) {
        FREE_AND_RETURN;
    }

    hMemoryDC = CreateCompatibleDC(hDesktopDC);
    if (hMemoryDC == NULL || fontFamily == NULL) {
        FREE_AND_RETURN;
    }
    err = SetMapMode(hMemoryDC, MM_TEXT);
    if (err == 0) {
        FREE_AND_RETURN;
    }

    memset(&lf, 0, sizeof(LOGFONTW));
    lf.lfHeight = -size;
    lf.lfWeight = (style & 1) ? FW_BOLD : FW_NORMAL;
    lf.lfItalic = (style & 2) ? 0xff : 0;
    lf.lfCharSet = DEFAULT_CHARSET;
    lf.lfQuality = CLEARTYPE_QUALITY;
    lf.lfOutPrecision = OUT_TT_PRECIS;
    lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
    lf.lfPitchAndFamily = DEFAULT_PITCH;

    nameLen = (*env)->GetStringLength(env, fontFamily);
    name = (LPWSTR)alloca((nameLen+1)*2);
    if (name == NULL) {
       FREE_AND_RETURN;
    }
    (*env)->GetStringRegion(env, fontFamily, 0, nameLen, name);
    name[nameLen] = '\0';

    if (nameLen < (sizeof(lf.lfFaceName) / sizeof(lf.lfFaceName[0]))) {
        wcscpy(lf.lfFaceName, name);
    } else {
        FREE_AND_RETURN;
    }

    hFont = CreateFontIndirectW(&lf);
    if (hFont == NULL) {
        FREE_AND_RETURN;
    }
    oldFont = SelectObject(hMemoryDC, hFont);

    memset(&textMetric, 0, sizeof(TEXTMETRIC));
    err = GetTextMetrics(hMemoryDC, &textMetric);
    if (err == 0) {
        FREE_AND_RETURN;
    }
    memset(&glyphMetrics, 0, sizeof(GLYPHMETRICS));
    memset(&mat2, 0, sizeof(MAT2));
    mat2.eM11.value = 1; mat2.eM22.value = 1;
    err = GetGlyphOutline(hMemoryDC, glyphCode,
                          GGO_METRICS|GGO_GLYPH_INDEX,
                          &glyphMetrics,
                          0, NULL, &mat2);
    if (err == GDI_ERROR) {
        /* Probably no such glyph - ie the font wasn't the one we expected. */
        FREE_AND_RETURN;
    }

    width  = (unsigned short)glyphMetrics.gmBlackBoxX;
    height = (unsigned short)glyphMetrics.gmBlackBoxY;

    /* Don't handle "invisible" glyphs in this code */
    if (width <= 0 || height == 0) {
       FREE_AND_RETURN;
    }

    advanceX = glyphMetrics.gmCellIncX;
    advanceY = glyphMetrics.gmCellIncY;
    topLeftX = glyphMetrics.gmptGlyphOrigin.x;
    topLeftY = glyphMetrics.gmptGlyphOrigin.y;

    /* GetGlyphOutline pre-dates cleartype and I'm not sure that it will
     * account for all pixels touched by the rendering. Need to widen,
     * and also adjust by one the x position at which it is rendered.
     * The extra pixels of width are used as follows :
     * One extra pixel at the left and the right will be needed to absorb
     * the pixels that will be touched by filtering by GDI to compensate
     * for colour fringing.
     * However there seem to be some cases where GDI renders two extra
     * pixels to the right, so we add one additional pixel to the right,
     * and in the code that copies this to the image cache we test for
     * the (rare) cases when this is touched, and if its not reduce the
     * stated image width for the blitting loops.
     * For fractional metrics :
     * One extra pixel at each end to account for sub-pixel positioning used
     * when fractional metrics is on in LCD mode.
     * The pixel at the left is needed so the blitting loop can index into
     * that a byte at a time to more accurately position the glyph.
     * The pixel at the right is needed so that when such indexing happens,
     * the blitting still can use the same width.
     * Consequently the width that is specified for the glyph is one less
     * than that of the actual image.
     * Note that in the FM case as a consequence we need to adjust the
     * position at which GDI renders, and the declared width of the glyph
     * See the if (fm) {} cases in the code.
     * For the non-FM case, we not only save 3 bytes per row, but this
     * prevents apparent glyph overlapping which affects the rendering
     * performance of accelerated pipelines since it adds additional
     * read-back requirements.
     */
    width+=3;
    if (fm) {
        width+=1;
    }
    /* DIB scanline must end on a DWORD boundary. We specify 3 bytes per pixel,
     * so must round up as needed to a multiple of 4 bytes.
     */
    dibBytesWidth = bytesWidth = width*3;
    extra = dibBytesWidth % 4;
    if (extra != 0) {
        dibBytesWidth += (4-extra);
    }
    /* The glyph cache image must be a multiple of 3 bytes wide. */
    extra = bytesWidth % 3;
    if (extra != 0) {
        bytesWidth += (3-extra);
    }
    bmWidth = width;
    bmHeight = height;

    /* Must use desktop DC to create a bitmap of that depth */
    hBitmap = CreateCompatibleBitmap(hDesktopDC, bmWidth, bmHeight);
    if (hBitmap == NULL) {
        FREE_AND_RETURN;
    }
    hOrigBM = (HBITMAP)SelectObject(hMemoryDC, hBitmap);

    /* Fill in black */
    rect.left = 0;
    rect.top = 0;
    rect.right = bmWidth;
    rect.bottom = bmHeight;
    FillRect(hMemoryDC, (LPRECT)&rect, GetStockObject(BLACK_BRUSH));

    /* Set text color to white, background to black. */
    SetBkColor(hMemoryDC, RGB(0,0,0));
    SetTextColor(hMemoryDC, RGB(255,255,255));

    /* adjust rendering position */
    x = -topLeftX+1;
    if (fm) {
        x += 1;
    }
    y = topLeftY - textMetric.tmAscent;
    err = ExtTextOutW(hMemoryDC, x, y, ETO_GLYPH_INDEX|ETO_OPAQUE,
                (LPRECT)&rect, (LPCWSTR)&glyphCode, 1, NULL);
    if (err == 0) {
        FREE_AND_RETURN;
    }

    /* Now get the image into a DIB.
     * MS docs for GetDIBits says the compatible bitmap must not be
     * selected into a DC, so restore the original first.
     */
    SelectObject(hMemoryDC, hOrigBM);
    SelectObject(hMemoryDC, oldFont);
    DeleteObject(hFont);

    memset(&bmi, 0, sizeof(BITMAPINFO));
    bmi.bmiHeader.biSize = sizeof(bmi.bmiHeader);
    bmi.bmiHeader.biWidth = width;
    bmi.bmiHeader.biHeight = -height;
    bmi.bmiHeader.biPlanes = 1;
    bmi.bmiHeader.biBitCount = 24;
    bmi.bmiHeader.biCompression = BI_RGB;

    dibImage = SAFE_SIZE_ARRAY_ALLOC(malloc, dibBytesWidth, height);
    if (dibImage == NULL) {
        FREE_AND_RETURN;
    }
    dibImageSize = dibBytesWidth*height;
    memset(dibImage, 0, dibImageSize);

    err = GetDIBits(hMemoryDC, hBitmap, 0, height, dibImage,
                    &bmi, DIB_RGB_COLORS);

    if (err == 0) {        /* GetDIBits failed. */
        FREE_AND_RETURN;
    }

    err = SystemParametersInfo(SPI_GETFONTSMOOTHINGORIENTATION, 0, &orient, 0);
    if (err == 0) {
        FREE_AND_RETURN;
    }
    err = SystemParametersInfo(SPI_GETFONTSMOOTHINGCONTRAST, 0, &gamma, 0);
    if (err == 0) {
        FREE_AND_RETURN;
    }
    igTable = getIGTable(gamma/10);
    if (igTable == NULL) {
        FREE_AND_RETURN;
    }

    /* Now copy glyph image into a GlyphInfo structure and return it.
     * NB the xadvance calculated here may be overwritten by the caller.
     * 1 is subtracted from the bitmap width to get the glyph width, since
     * that extra "1" was added as padding, so the sub-pixel positioning of
     * fractional metrics could index into it.
     */
    glyphInfo = (GlyphInfo*)SAFE_SIZE_STRUCT_ALLOC(malloc, sizeof(GlyphInfo),
            bytesWidth, height);
    if (glyphInfo == NULL) {
        FREE_AND_RETURN;
    }
    imageSize = bytesWidth*height;
    glyphInfo->cellInfo = NULL;
    glyphInfo->rowBytes = bytesWidth;
    glyphInfo->width = width;
    if (fm) {
        glyphInfo->width -= 1; // must subtract 1
    }
    glyphInfo->height = height;
    glyphInfo->advanceX = advanceX;
    glyphInfo->advanceY = advanceY;
    glyphInfo->topLeftX = (float)(topLeftX-1);
    if (fm) {
        glyphInfo->topLeftX -= 1;
    }
    glyphInfo->topLeftY = (float)-topLeftY;
    glyphInfo->image = (unsigned char*)glyphInfo+sizeof(GlyphInfo);
    memset(glyphInfo->image, 0, imageSize);

    /* DIB 24bpp data is always stored in BGR order, but we usually
     * need this in RGB, so we can't just memcpy and need to swap B and R.
     * Also need to apply inverse gamma adjustment here.
     * We re-use the variable "extra" to see if the last pixel is touched
     * at all. If its not we can reduce the glyph image width. This comes
     * into play in some cases where GDI touches more pixels than accounted
     * for by increasing width by two pixels over the B&W image. Whilst
     * the bytes are in the cache, it doesn't affect rendering performance
     * of the hardware pipelines.
     */
    extra = 0;
    if (fm) {
        extra = 1; // always need it.
    }
    dibRowPtr = dibImage;
    rowPtr = glyphInfo->image;
    for (y=0;y<height;y++) {
        pixelPtr = rowPtr;
        dibPixPtr = dibRowPtr;
        for (x=0;x<width;x++) {
            if (orient == FE_FONTSMOOTHINGORIENTATIONRGB) {
                b = *dibPixPtr++;
                g = *dibPixPtr++;
                r = *dibPixPtr++;
            } else {
                r = *dibPixPtr++;
                g = *dibPixPtr++;
                b = *dibPixPtr++;
            }
            *pixelPtr++ = igTable[r];
            *pixelPtr++ = igTable[g];
            *pixelPtr++ = igTable[b];
            if (!fm && (x==(width-1)) && (r|g|b)) {
                extra = 1;
            }
        }
        dibRowPtr += dibBytesWidth;
        rowPtr  += bytesWidth;
    }
    if (!extra) {
        glyphInfo->width -= 1;
    }

    free(dibImage);
    ReleaseDC(hWnd, hDesktopDC);
    DeleteObject(hMemoryDC);
    DeleteObject(hBitmap);

    return ptr_to_jlong(glyphInfo);
}
예제 #24
0
static CGPathRef createPathForGlyph(HDC hdc, Glyph glyph)
{
    CGMutablePathRef path = CGPathCreateMutable();

    static const MAT2 identity = { 0, 1,  0, 0,  0, 0,  0, 1 };
    GLYPHMETRICS glyphMetrics;
    // GGO_NATIVE matches the outline perfectly when Windows font smoothing is off.
    // GGO_NATIVE | GGO_UNHINTED does not match perfectly either when Windows font smoothing is on or off.
    DWORD outlineLength = GetGlyphOutline(hdc, glyph, GGO_GLYPH_INDEX | GGO_NATIVE, &glyphMetrics, 0, 0, &identity);
    ASSERT(outlineLength >= 0);
    if (outlineLength < 0)
        return path;

    Vector<UInt8> outline(outlineLength);
    GetGlyphOutline(hdc, glyph, GGO_GLYPH_INDEX | GGO_NATIVE, &glyphMetrics, outlineLength, outline.data(), &identity);

    unsigned offset = 0;
    while (offset < outlineLength) {
        LPTTPOLYGONHEADER subpath = reinterpret_cast<LPTTPOLYGONHEADER>(outline.data() + offset);
        ASSERT(subpath->dwType == TT_POLYGON_TYPE);
        if (subpath->dwType != TT_POLYGON_TYPE)
            return path;

        CGPathMoveToPoint(path, 0, toCGFloat(subpath->pfxStart.x), toCGFloat(subpath->pfxStart.y));

        unsigned subpathOffset = sizeof(*subpath);
        while (subpathOffset < subpath->cb) {
            LPTTPOLYCURVE segment = reinterpret_cast<LPTTPOLYCURVE>(reinterpret_cast<UInt8*>(subpath) + subpathOffset);
            switch (segment->wType) {
            case TT_PRIM_LINE:
                for (unsigned i = 0; i < segment->cpfx; i++)
                    CGPathAddLineToPoint(path, 0, toCGFloat(segment->apfx[i].x), toCGFloat(segment->apfx[i].y));
                break;

            case TT_PRIM_QSPLINE:
                for (unsigned i = 0; i < segment->cpfx; i++) {
                    CGFloat x = toCGFloat(segment->apfx[i].x);
                    CGFloat y = toCGFloat(segment->apfx[i].y);
                    CGFloat cpx;
                    CGFloat cpy;

                    if (i == segment->cpfx - 2) {
                        cpx = toCGFloat(segment->apfx[i + 1].x);
                        cpy = toCGFloat(segment->apfx[i + 1].y);
                        i++;
                    } else {
                        cpx = (toCGFloat(segment->apfx[i].x) + toCGFloat(segment->apfx[i + 1].x)) / 2;
                        cpy = (toCGFloat(segment->apfx[i].y) + toCGFloat(segment->apfx[i + 1].y)) / 2;
                    }

                    CGPathAddQuadCurveToPoint(path, 0, x, y, cpx, cpy);
                }
                break;

            case TT_PRIM_CSPLINE:
                for (unsigned i = 0; i < segment->cpfx; i += 3) {
                    CGFloat cp1x = toCGFloat(segment->apfx[i].x);
                    CGFloat cp1y = toCGFloat(segment->apfx[i].y);
                    CGFloat cp2x = toCGFloat(segment->apfx[i + 1].x);
                    CGFloat cp2y = toCGFloat(segment->apfx[i + 1].y);
                    CGFloat x = toCGFloat(segment->apfx[i + 2].x);
                    CGFloat y = toCGFloat(segment->apfx[i + 2].y);

                    CGPathAddCurveToPoint(path, 0, cp1x, cp1y, cp2x, cp2y, x, y);
                }
                break;

            default:
                ASSERT_NOT_REACHED();
                return path;
            }

            subpathOffset += sizeof(*segment) + (segment->cpfx - 1) * sizeof(segment->apfx[0]);
        }
        CGPathCloseSubpath(path);
        offset += subpath->cb;
    }
    return path;
}
// CreateFontManageData のWindows環境依存処理を行う関数
static int CreateFontManageData_Win( FONTMANAGE *ManageData, int DefaultCharSet )
{
	int CreateFontSize ;
	int SampleScale ;
	int EnableAddHeight	= FALSE ;
	int	AddHeight		= 0 ;
	int	OrigHeight		= 0 ;

	switch( ManageData->ImageBitDepth )
	{
	default:
	case DX_FONTIMAGE_BIT_1:
		SampleScale = 1 ;
		break ;

	case DX_FONTIMAGE_BIT_4:
		SampleScale = 4 ;
		break ;

	case DX_FONTIMAGE_BIT_8:
		SampleScale = 16 ;
		break ;
	}
	CreateFontSize = ManageData->BaseInfo.FontSize * SampleScale ;

CREATEFONTLABEL:

	// 既にフォントが作成されていたら削除
	if( ManageData->FontObj != NULL )
	{
		DeleteObject( ManageData->FontObj ) ;
	}

	if( ManageData->FontName[0] != L'\0' )
	{
		// 特に文字セットの指定が無い場合で、且つ指定のフォント名の指定の文字セットが無い場合は文字セットを DEFAULT_CHARSET にする
		if( DefaultCharSet == TRUE )
		{
			wchar_t	TempNameBuffer[ 16 ][ 64 ] ;
			wchar_t	*TempNameBufferP ;
			int		TempNameNum ;
			int		TempNameBufferAlloc ;
			int		i ;

			TempNameNum = EnumFontName( TempNameBuffer[ 0 ], 16, ManageData->BaseInfo.CharSet, ManageData->FontName ) ;
			if( TempNameNum >= 16 )
			{
				TempNameNum			= EnumFontName( NULL,            0,           ManageData->BaseInfo.CharSet, ManageData->FontName ) ;
				TempNameBufferP		= ( wchar_t * )malloc( TempNameNum * 64 * sizeof( wchar_t ) ) ;
				TempNameNum			= EnumFontName( TempNameBufferP, TempNameNum, ManageData->BaseInfo.CharSet, ManageData->FontName ) ;
				TempNameBufferAlloc = TRUE ;
			}
			else
			{
				TempNameBufferAlloc = FALSE ;
				TempNameBufferP		= TempNameBuffer[ 0 ] ;
			}

			for( i = 0 ; i < TempNameNum && CL_strcmp( CODEPAGE_UTF16LE, ( char * )( TempNameBufferP + i * 64 ), ( char * )ManageData->FontName ) != 0 ; i ++ ){}
			if( i == TempNameNum )
			{
				ManageData->BaseInfo.CharSet = DX_CHARSET_DEFAULT ;
			}

			if( TempNameBufferAlloc )
			{
				free( TempNameBufferP ) ;
				TempNameBufferP = NULL ;
			}
		}

		ManageData->FontObj = CreateFontW(
			CreateFontSize + AddHeight, 0, 0, 0,
			ManageData->BaseInfo.FontThickness * 100,
			ManageData->BaseInfo.Italic, FALSE, FALSE,
			CharSetTable[ ManageData->BaseInfo.CharSet ],
			OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
			NONANTIALIASED_QUALITY, FIXED_PITCH,
			ManageData->FontName
		) ;

		if( ManageData->FontObj == NULL )
		{
			ManageData->FontObj = CreateFontW(
				CreateFontSize + AddHeight, 0, 0, 0,
				ManageData->BaseInfo.FontThickness * 100,
				ManageData->BaseInfo.Italic, FALSE, FALSE,
				DEFAULT_CHARSET,
				OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
				NONANTIALIASED_QUALITY, FIXED_PITCH,
				ManageData->FontName
			) ;

			if( ManageData->FontObj == NULL )
			{
				ManageData->FontObj = CreateFontW(
					CreateFontSize + AddHeight, 0, 0, 0,
					ManageData->BaseInfo.FontThickness * 100,
					ManageData->BaseInfo.Italic, FALSE, FALSE,
					SHIFTJIS_CHARSET,
					OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
					NONANTIALIASED_QUALITY, FIXED_PITCH,
					ManageData->FontName
				) ;

				if( ManageData->FontObj == NULL )
				{
					wprintf( L"指定のフォントの作成に失敗しました\n" ) ;
					goto ERR ;
				}
			}
		}
	}
	else
	{
		ManageData->FontObj = CreateFontW(
			CreateFontSize + AddHeight, 0, 0, 0,
			ManageData->BaseInfo.FontThickness * 100,
			ManageData->BaseInfo.Italic, FALSE, FALSE,
			CharSetTable[ ManageData->BaseInfo.CharSet ],
			OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
			NONANTIALIASED_QUALITY, FIXED_PITCH,
			L"MS ゴシック"
		) ;
		ManageData->FontName[0] = L'\0' ;
	}

	if( ManageData->FontObj == NULL )
	{
		ManageData->FontObj = CreateFontW(
			CreateFontSize + AddHeight, 0, 0, 0,
			ManageData->BaseInfo.FontThickness * 100,
			FALSE, FALSE, FALSE,
			DEFAULT_CHARSET,
			OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
			NONANTIALIASED_QUALITY, FIXED_PITCH,
			L"MS ゴシック"
		) ;

		if( ManageData->FontObj == NULL )
		{
			ManageData->FontObj = CreateFontW(
				CreateFontSize + AddHeight, 0, 0, 0,
				ManageData->BaseInfo.FontThickness * 100,
				FALSE, FALSE, FALSE,
				DEFAULT_CHARSET,
				OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS,
				NONANTIALIASED_QUALITY, FIXED_PITCH,
				NULL
			) ;
		}
		ManageData->FontName[0] = L'\0' ;

		if( ManageData->FontObj == NULL )
		{
			wprintf( L"フォントの作成に失敗しました\n" ) ;
			goto ERR ;
		}
	}

	// 文字のサイズを取得する
	{
		HDC			DC ;
		HFONT		OldFont ;
		TEXTMETRIC	TextInfo ;

		// デバイスコンテキストを取得
		DC = CreateCompatibleDC( NULL ) ;
		if( DC == NULL )
		{
			wprintf( L"デバイスコンテキストの取得に失敗しました\n" ) ;
			goto ERR ;
		}

		// フォントのセット
		OldFont = ( HFONT )SelectObject( DC, ManageData->FontObj ) ;

		// フォントのステータスを取得
		GetTextMetrics( DC, &TextInfo ) ;

		// もし TextInfo.tmInternalLeading + TextInfo.tmExternalLeading が 0 ではなかったらその高さを追加してフォントを作成しなおす
		if( EnableAddHeight == FALSE )
		{
			if( TextInfo.tmInternalLeading + TextInfo.tmExternalLeading > 0 )
			{
				OrigHeight		= TextInfo.tmHeight ;
				AddHeight		= ( int )( CreateFontSize / ( 1.0f - ( float )( TextInfo.tmInternalLeading + TextInfo.tmExternalLeading ) / TextInfo.tmHeight ) ) - CreateFontSize ;
				EnableAddHeight	= TRUE ;

				SelectObject( DC, OldFont ) ;
				DeleteDC( DC ) ;

				DeleteObject( ManageData->FontObj ) ;
				ManageData->FontObj = NULL ;

				goto CREATEFONTLABEL ;
			}
			
			ManageData->BaseInfo.FontAddHeight = 0 ;
		}
		else
		{
			ManageData->BaseInfo.FontAddHeight = ( WORD )( ( TextInfo.tmHeight - OrigHeight ) / SampleScale ) ;
		}

		// フォントの最大サイズを取得
		if( ManageData->BaseInfo.Italic )
		{
			// イタリック体の場合は最大幅が 1.35倍になる
			ManageData->BaseInfo.MaxWidth = ( WORD )( ( TextInfo.tmMaxCharWidth * 135 / SampleScale + 4 * 135 ) / 100 ) ;
		}
		else
		{
			ManageData->BaseInfo.MaxWidth = ( WORD )( TextInfo.tmMaxCharWidth / SampleScale + 4 ) ;
		}

		// フォントの高さを保存
		ManageData->BaseInfo.FontHeight = ( WORD )( TextInfo.tmHeight / SampleScale + 1 ) ;

		// GetGlyphOutline が使用できるかどうかを調べる
		{
			GLYPHMETRICS	gm ;
			MAT2			mt = { { 0, 1 }, { 0, 0 }, { 0, 0 }, { 0, 1 } } ;
			unsigned int	Code ;
			DWORD			DataSize ;

			memset( &gm, 0, sizeof( GLYPHMETRICS ) ) ;
			Code		= ' ' ;
			DataSize	= GetGlyphOutline( DC, Code, GGO_BITMAP, &gm, 0, NULL, &mt ) ;

			// 失敗した場合は TextOut 方式を使用する
			if( DataSize == GDI_ERROR )
			{
				ManageData->UseTextOut = TRUE ;
			}
		}

		// TextOut 方式を使用する場合は DIB を作成しておく
		ManageData->CacheBitmap			= NULL ;
		ManageData->CacheBitmapMem		= NULL ;
		ManageData->CacheBitmapMemPitch	= 0 ;
		if( ManageData->UseTextOut )
		{
			BITMAPINFO	*BmpInfoPlus ;
			BITMAP		BmpData ;

			// イメージビット深度も DX_FONTIMAGE_BIT_1 のみ
			ManageData->ImageBitDepth = DX_FONTIMAGE_BIT_1 ;

			// キャッシュ領域のステータスの初期化
			BmpInfoPlus = ( BITMAPINFO * )malloc( sizeof( BITMAPINFO ) + sizeof( RGBQUAD ) * 256 ) ;
			if( BmpInfoPlus == NULL )
			{
				wprintf( L"メモリの確保に失敗しました" ) ;
				return -1 ;
			}
			BmpInfoPlus->bmiHeader.biSize			= sizeof( BITMAPINFOHEADER ) ;
			BmpInfoPlus->bmiHeader.biWidth			=  ManageData->BaseInfo.MaxWidth ;
			BmpInfoPlus->bmiHeader.biHeight			= -ManageData->BaseInfo.MaxWidth ;
			BmpInfoPlus->bmiHeader.biPlanes			= 1 ;
			BmpInfoPlus->bmiHeader.biBitCount		= 8 ;
			BmpInfoPlus->bmiHeader.biCompression	= BI_RGB ;
			BmpInfoPlus->bmiHeader.biSizeImage		= ( DWORD )( ManageData->BaseInfo.MaxWidth * ManageData->BaseInfo.MaxWidth ) ;

			// カラーパレットのセット
			{
				RGBQUAD *Color ;
				int		i ;

				Color = &BmpInfoPlus->bmiColors[0] ;
				for( i = 0 ; i < 256 ; i ++ )
				{
					Color->rgbBlue     = ( BYTE )i ;
					Color->rgbRed      = ( BYTE )i ;
					Color->rgbBlue     = ( BYTE )i ;
					Color->rgbReserved = 0 ;

					Color ++ ;
				}
			}

			// DIBデータを作成する
			ManageData->CacheBitmapMem	= NULL ; 
			ManageData->CacheBitmap		= CreateDIBSection( DC, BmpInfoPlus, DIB_PAL_COLORS, ( void ** )&ManageData->CacheBitmapMem, NULL, 0 ) ;

			// ピッチを得る
			GetObject( ManageData->CacheBitmap, sizeof( BITMAP ), &BmpData ) ;
			ManageData->CacheBitmapMemPitch = BmpData.bmWidthBytes ;

			// メモリの解放
			free( BmpInfoPlus ) ;
		}

		// フォントを元に戻す
		SelectObject( DC, OldFont ) ;

		// デバイスコンテキストを削除する
		DeleteDC( DC ) ;
	}

	// 正常終了
	return 0 ;

	// エラー処理
ERR :

	return -1 ;
}
예제 #26
0
//�������������������������������������������������������������������������Ŀ
// capture_tt                                                               �
//                                                                          �
// Captures a TrueType font into the output IFF (already open by main)      �
//���������������������������������������������������������������������������
void capture_tt(char *name, char *ttname,
                ushort width, ushort height,
                byte startc, ushort numc)
{
    int                 j;
    byte                *font, *fptr;
    ulong               fontSize;
    GBergFileFontHDR    header;
    byte                work[4096];

    assert(name != 0 && ttname != 0 && height > 0);

    memset(&header,0,sizeof(header));
    strncpy(header.name,name,sizeof(header.name));

    if (((int)startc+(int)numc-1) > 256)
    {
        cout << "��� Error: number of characters in set must fit in 128 or 256 chars";
        exit(1);
    }

    int numchars = (((int)startc+(int)numc-1) > 128) ? 256 : 128;

//��� Find and select font that meets input criteria
    HWND hWnd = GetDesktopWindow();
    assert(hWnd != 0);

    HDC hDC = GetDC(hWnd);
    assert(hDC != 0);

    HFONT               hFont, hOldFont;
    OUTLINETEXTMETRIC   tm;
    for(;;)
    {
        LOGFONT fontinfo;
        memset(&fontinfo,0,sizeof(fontinfo));
        fontinfo.lfHeight = height;
        if (Flags & FLAGS_TT_BOLD)
            fontinfo.lfWeight = FW_BOLD;
        if (Flags & FLAGS_TT_ITALIC)
            fontinfo.lfItalic = TRUE;
        if (Flags & FLAGS_TT_UNDERLINE)
            fontinfo.lfUnderline = TRUE;
        if (Flags & FLAGS_TT_STRIKEOUT)
            fontinfo.lfStrikeOut = TRUE;
        if (Flags & FLAGS_TT_OEMCHARSET)
            fontinfo.lfCharSet = OEM_CHARSET;
        fontinfo.lfOutPrecision = OUT_TT_ONLY_PRECIS;
        strncpy(fontinfo.lfFaceName,ttname,sizeof(fontinfo.lfFaceName));

        hFont = CreateFontIndirect(&fontinfo);
        if (!hFont)
        {
            cout << "��� Error: failed to get TrueType font with specified characteristics";
            ReleaseDC(hWnd,hDC);
            exit(1);
        }

        hOldFont = (HFONT__*)SelectObject(hDC,hFont);

        memset(&tm,0,sizeof(tm));
        GetOutlineTextMetrics(hDC,sizeof(tm),&tm);

        if (!width || tm.otmTextMetrics.tmMaxCharWidth <= width)
        {
            break;
        }
        else if (height <= 1)
        {
            cout << "��� Error: failed to get TrueType font with specified characteristics\n";
            SelectObject(hDC,hOldFont);
            DeleteObject(hFont);
            ReleaseDC(hWnd,hDC);
            exit(1);
        }
        else
        {
            height--;
            SelectObject(hDC,hOldFont);
        }
    }

//��� See if we can download bitmap for font...
    {
        GLYPHMETRICS glyph;
        MAT2 matrix;
        memset(&matrix,0,sizeof(matrix));
        matrix.eM11.value = 1;
        matrix.eM22.value = 1;

        if (GetGlyphOutline(hDC,0,GGO_BITMAP,&glyph,0,0,&matrix) == GDI_ERROR)
        {
            cout << "��� Error: Can't capture data for specified font characteristics\n";
            SelectObject(hDC,hOldFont);
            DeleteObject(hFont);
            ReleaseDC(hWnd,hDC);
            exit(1);
        }
    }

//��� Output information about selected font
    if (!(Flags & FLAGS_QUIET))
    {
        cout << "Capturing TrueType font '" << ttname << "'...\n";
        cout << "   Size: " << tm.otmTextMetrics.tmMaxCharWidth
             << " by " << tm.otmTextMetrics.tmHeight << endl;
        cout << "   Character #" << (int)startc << " to #" << ((int)startc+(int)numc-1) << endl;
        if (tm.otmfsType & 0x1)
            cout << "   *Licensed font*";
        cout << "   Attributes: ";

        switch (tm.otmTextMetrics.tmWeight)
        {
            case FW_THIN:
                cout << "Thin ";
                break;
            case FW_EXTRALIGHT:
                cout << "ExtraLight ";
                break;
            case FW_LIGHT:
                cout << "Light ";
                break;
            case FW_NORMAL:
                cout << "Normal ";
                break;
            case FW_MEDIUM:
                cout << "Medium ";
                break;
            case FW_SEMIBOLD:
                cout << "SemiBold ";
                break;
            case FW_BOLD:
                cout << "Bold ";
                break;
            case FW_EXTRABOLD:
                cout << "ExtraBold ";
                break;
            case FW_HEAVY:
                cout << "Heavy ";
                break;
            default:
                cout << "Wght(" << tm.otmTextMetrics.tmWeight << ") ";
                break;
        }
        if (tm.otmTextMetrics.tmItalic)
            cout << "Italic ";
        if (tm.otmTextMetrics.tmUnderlined)
            cout << "Underlined ";
        if (tm.otmTextMetrics.tmStruckOut)
            cout << "StruckOut ";
        if (tm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)
            cout << "Variable-pitch ";
        else
            cout << "Fixed-pitch ";
        cout << endl;

        cout << "   Family: ";
        if (tm.otmTextMetrics.tmPitchAndFamily & FF_MODERN)
            cout << "Modern ";
        if (tm.otmTextMetrics.tmPitchAndFamily & FF_ROMAN)
            cout << "Roman ";
        if (tm.otmTextMetrics.tmPitchAndFamily & FF_SCRIPT)
            cout << "Script ";
        if (tm.otmTextMetrics.tmPitchAndFamily & FF_SWISS)
            cout << "Swiss ";
        if (tm.otmTextMetrics.tmPitchAndFamily & FF_DECORATIVE)
            cout << "Decorative ";
        cout << endl;

        cout << "   CharSet: ";
        switch (tm.otmTextMetrics.tmCharSet)
        {
            case ANSI_CHARSET:
                cout << "ANSI ";
                break;
            case SYMBOL_CHARSET:
                cout << "Symbol ";
                break;
            case OEM_CHARSET:
                cout << "OEM ";
                break;
            default:
                cout << "#" << tm.otmTextMetrics.tmCharSet;
                break;
        }
        cout << endl;

        if ((numchars > 128) && (Flags & FLAGS_TT_CP850))
        {
            cout << "   Map special characters to Codepage 850\n";
        }
    }

    if (tm.otmTextMetrics.tmMaxCharWidth > 32)
    {
        cout << "��� Error: Maximum width must be less than or equal to 32";
        SelectObject(hDC,hOldFont);
        DeleteObject(hFont);
        ReleaseDC(hWnd,hDC);
        exit(1);
    }

//�� Font Header
    header.width = (ushort)tm.otmTextMetrics.tmMaxCharWidth;
    header.height = (ushort)tm.otmTextMetrics.tmHeight;

    // Only supports MONO non-COMPRESSED fonts
    header.compression = 0;
    if (tm.otmTextMetrics.tmPitchAndFamily & TMPF_FIXED_PITCH)
    {
        // Variable
        header.type = (numchars > 128) ? GBERG_FNT_MONOVARIABLEEX
                                       : GBERG_FNT_MONOVARIABLE;
        header.bpc = (ushort)((((header.width + 7) >> 3) * header.height) + 1);
    }
예제 #27
0
bool CreateFontTexture
(
 IDirect3DDevice9* pDev,
 DWORD usage,
 D3DPOOL pool,
 UINT ch,
 Font* pFont
) {
   HDC hdc = GetDC(NULL);
   HFONT hFont = ::CreateFont(0, 0, 0, 0, FW_DONTCARE, FALSE, FALSE, FALSE, DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH, _T("MS UI Gothic")); 
   HFONT hOldFont = (HFONT)::SelectObject(hdc, hFont); 

   HRESULT hr;
   int gm_w, gm_h;
   int fnt_x, fnt_y;
   BYTE *bmp_p = NULL;
   int bmp_w, bmp_h; //bmp_p
   {
      TEXTMETRIC tm;
      GLYPHMETRICS gm;
      MAT2 mat2 = { {0,1}, {0,0}, {0,0}, {0,1} };

      GetTextMetrics(hdc, &tm);
      DWORD bufsize = GetGlyphOutline(
         hdc, ch, GGO_GRAY4_BITMAP, &gm, 0, NULL, &mat2);
      if (bufsize == GDI_ERROR) {
         bufsize = GetLastError();
         goto fin;
      }
      bmp_p = (BYTE*)malloc(bufsize);
      DWORD r = GetGlyphOutline(
         hdc, ch, GGO_GRAY4_BITMAP, &gm, bufsize, bmp_p, &mat2);

      pFont->tm_max_w = tm.tmMaxCharWidth;
      pFont->tm_ave_w = tm.tmAveCharWidth;
      gm_w = gm.gmCellIncX;
      gm_h = tm.tmHeight;
      bmp_w = ((gm.gmBlackBoxX + 3) / 4) * 4; //4-align
      bmp_h = gm.gmBlackBoxY;
      fnt_x = gm.gmptGlyphOrigin.x;
      fnt_y = tm.tmAscent - gm.gmptGlyphOrigin.y;
   }

   IDirect3DTexture9* pTex;
   hr = pDev->CreateTexture(gm_w, gm_h, 1,
      usage, D3DFMT_A8R8G8B8, pool,
      &pTex, NULL);

   {
      D3DLOCKED_RECT rect;
      pTex->LockRect(0, &rect, NULL, D3DLOCK_DISCARD);
      FillMemory(rect.pBits, rect.Pitch * gm_h, 0);
      for (int y=0; y<bmp_h; ++y) {
         BYTE* p = ((BYTE*)rect.pBits) + rect.Pitch * (fnt_y + y) + fnt_x * 4;
         for (int x=0; x<bmp_w; ++x) {
            DWORD trans = ((255 * bmp_p[x+y*bmp_w]) /16)&0xFF;
            DWORD color = 0x00FFFFFF | (trans << 24);
            memcpy(p, &color, 4);
            p += 4;
         }
      }
      pTex->UnlockRect(0);
   }
   pFont->pTex = pTex;
   pFont->gm_w = gm_w;
   pFont->gm_h = gm_h;
   pFont->fnt_x = fnt_x;
   pFont->fnt_y = fnt_y;

fin:
   if (bmp_p) { free(bmp_p); }
   SelectObject(hdc, hOldFont); 
   return true;
}
예제 #28
0
파일: ft_tt.c 프로젝트: Gaikokujin/WinNT4
BOOL bTestGGO (
    HDC     hdc,
    LPMAT2  lpmat2
    )
{
    ULONG   row = 0;                    // screen row coordinate to print at
    ULONG   rowIncr;
    HFONT   hfont;
    HFONT   hfontOriginal;
    LOGFONT lfnt;
    TEXTMETRIC  tm;

    ULONG   cjBuffer;
    PBYTE   pjBuffer;

    GLYPHMETRICS    gm;

// Clear the screen to black.

    BitBlt(hdc, 0, 0, CX, CY, (HDC) 0, 0, 0, 0);

// Get a font.

    memset(&lfnt, 0, sizeof(lfnt));
    lstrcpy(lfnt.lfFaceName, "Lucida Fax");
    lfnt.lfHeight = 24;
    lfnt.lfWeight = 400;

    if ((hfont = CreateFontIndirect(&lfnt)) == NULL)
    {
        DbgPrint("ft!bTestGGO(): Logical font creation failed.\n");
        return FALSE;
    }

    hfontOriginal = SelectObject(hdc, hfont);

// Get textmetrics.

    if ( !GetTextMetrics(hdc, &tm) )
    {
        DbgPrint("ft!bTestGGO(): GetTextMetrics failed\n");
        return FALSE;
    }

    rowIncr = tm.tmHeight + tm.tmExternalLeading;

// Determine buffer size needed by GetGlyphOutline.

    if ( (cjBuffer = (ULONG) GetGlyphOutline(hdc, 0x0054, GGO_BITMAP, &gm, 0, (PVOID) NULL, lpmat2)) == (ULONG) -1 )
    {
        DbgPrint("ft!bTestGGO(): could not get buffer size from API\n");
        return FALSE;
    }

// Allocate memory.

    DbgPrint("ft!bTestGGO(): allocating 0x%lx bytes for buffer\n", cjBuffer);
    if ( (pjBuffer = (PBYTE) LocalAlloc(LPTR, cjBuffer)) == (PBYTE) NULL )
    {
        DbgPrint("ft!bTestGGO(): LocalAlloc(LPTR, 0x%lx) failed\n", cjBuffer);
        return FALSE;
    }

// Get the bitmap.

    if ( GetGlyphOutline(hdc, 0x0054, GGO_BITMAP, &gm, cjBuffer, (PVOID) pjBuffer, lpmat2) == (DWORD) -1 )
    {
        LocalFree(pjBuffer);

        DbgPrint("ft!bTestGGO(): call to GetFontData failed\n");
        return FALSE;
    }

// Print out GLYPHMETRIC data.

    sprintf(szOutText, "gmBlackBoxX: %ld", gm.gmBlackBoxX);
    TextOut(hdc, 0, row, szOutText, strlen(szOutText));
    row += rowIncr;

    sprintf(szOutText, "gmBlackBoxY: %ld", gm.gmBlackBoxY);
    TextOut(hdc, 0, row, szOutText, strlen(szOutText));
    row += rowIncr;

    sprintf(szOutText, "gmptGlyphOrigin: (%ld, %ld)", gm.gmptGlyphOrigin.x, gm.gmptGlyphOrigin.y);
    TextOut(hdc, 0, row, szOutText, strlen(szOutText));
    row += rowIncr;

    sprintf(szOutText, "gmCellIncX: %ld", gm.gmCellIncX);
    TextOut(hdc, 0, row, szOutText, strlen(szOutText));
    row += rowIncr;

    sprintf(szOutText, "gmCellIncY: %ld", gm.gmCellIncY);
    TextOut(hdc, 0, row, szOutText, strlen(szOutText));
    row += rowIncr;

// Flush out batched calls.

    GdiFlush();

// Allow an opportunity to examine the contents.

    DbgPrint("ft!bTestGGO(): call to GetGlyphOutline succeeded\n");
    DbgPrint("\tbitmap is at 0x%lx, size is 0x%lx (%ld)\n", pjBuffer, cjBuffer, cjBuffer);
    DbgBreakPoint();

// Restore the font.

    SelectObject(hdc, hfontOriginal);
    DeleteObject(hfont);

    return TRUE;
}
예제 #29
0
void font_instance::LoadGlyph(int glyph_id)
{
    if ( pFont == NULL ) {
        return;
    }
    InitTheFace();
#ifndef USE_PANGO_WIN32
    if ( !FT_IS_SCALABLE(theFace) ) {
        return; // bitmap font
    }
#endif

    if ( id_to_no.find(glyph_id) == id_to_no.end() ) {
        Geom::PathBuilder path_builder;

        if ( nbGlyph >= maxGlyph ) {
            maxGlyph=2*nbGlyph+1;
            glyphs=(font_glyph*)realloc(glyphs,maxGlyph*sizeof(font_glyph));
        }
        font_glyph  n_g;
        n_g.pathvector=NULL;
        n_g.bbox[0]=n_g.bbox[1]=n_g.bbox[2]=n_g.bbox[3]=0;
        n_g.h_advance = 0;
        n_g.v_advance = 0;
        n_g.h_width = 0;
        n_g.v_width = 0;
        bool   doAdd=false;

#ifdef USE_PANGO_WIN32

#ifndef GGO_UNHINTED         // For compatibility with old SDKs.
#define GGO_UNHINTED 0x0100
#endif

        MAT2 identity = {{0,1},{0,0},{0,0},{0,1}};
        OUTLINETEXTMETRIC otm;
        GetOutlineTextMetrics(daddy->hScreenDC, sizeof(otm), &otm);
        GLYPHMETRICS metrics;
        DWORD bufferSize=GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, 0, NULL, &identity);
        double scale=1.0/daddy->fontSize;
        n_g.h_advance=metrics.gmCellIncX*scale;
        n_g.v_advance=otm.otmTextMetrics.tmHeight*scale;
        n_g.h_width=metrics.gmBlackBoxX*scale;
        n_g.v_width=metrics.gmBlackBoxY*scale;
        if ( bufferSize == GDI_ERROR) {
            // shit happened
        } else if ( bufferSize == 0) {
            // character has no visual representation, but is valid (eg whitespace)
            doAdd=true;
        } else {
            char *buffer = new char[bufferSize];
            if ( GetGlyphOutline (daddy->hScreenDC, glyph_id, GGO_GLYPH_INDEX | GGO_NATIVE | GGO_UNHINTED, &metrics, bufferSize, buffer, &identity) <= 0 ) {
                // shit happened
            } else {
                // Platform SDK is rubbish, read KB87115 instead
                DWORD polyOffset=0;
                while ( polyOffset < bufferSize ) {
                    TTPOLYGONHEADER const *polyHeader=(TTPOLYGONHEADER const *)(buffer+polyOffset);
                    if (polyOffset+polyHeader->cb > bufferSize) break;

                    if (polyHeader->dwType == TT_POLYGON_TYPE) {
                        path_builder.moveTo(pointfx_to_nrpoint(polyHeader->pfxStart, scale));
                        DWORD curveOffset=polyOffset+sizeof(TTPOLYGONHEADER);

                        while ( curveOffset < polyOffset+polyHeader->cb ) {
                            TTPOLYCURVE const *polyCurve=(TTPOLYCURVE const *)(buffer+curveOffset);
                            POINTFX const *p=polyCurve->apfx;
                            POINTFX const *endp=p+polyCurve->cpfx;

                            switch (polyCurve->wType) {
                            case TT_PRIM_LINE:
                                while ( p != endp )
                                    path_builder.lineTo(pointfx_to_nrpoint(*p++, scale));
                                break;

                            case TT_PRIM_QSPLINE:
                                {
                                    g_assert(polyCurve->cpfx >= 2);

                                    // The list of points specifies one or more control points and ends with the end point.
                                    // The intermediate points (on the curve) are the points between the control points.
                                    Geom::Point this_control = pointfx_to_nrpoint(*p++, scale);
                                    while ( p+1 != endp ) { // Process all "midpoints" (all points except the last)
                                        Geom::Point new_control = pointfx_to_nrpoint(*p++, scale);
                                        path_builder.quadTo(this_control, (new_control+this_control)/2);
                                        this_control = new_control;
                                    }
                                    Geom::Point end = pointfx_to_nrpoint(*p++, scale);
                                    path_builder.quadTo(this_control, end);
                                }
                                break;

                            case 3:  // TT_PRIM_CSPLINE
                                g_assert(polyCurve->cpfx % 3 == 0);
                                while ( p != endp ) {
                                    path_builder.curveTo(pointfx_to_nrpoint(p[0], scale),
                                                         pointfx_to_nrpoint(p[1], scale),
                                                         pointfx_to_nrpoint(p[2], scale));
                                    p += 3;
                                }
                                break;
                            }
                            curveOffset += sizeof(TTPOLYCURVE)+sizeof(POINTFX)*(polyCurve->cpfx-1);
                        }
                    }
                    polyOffset += polyHeader->cb;
                }
                doAdd=true;
            }
            delete [] buffer;
        }
#else
        if (FT_Load_Glyph (theFace, glyph_id, FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP)) {
            // shit happened
        } else {
            if ( FT_HAS_HORIZONTAL(theFace) ) {
                n_g.h_advance=((double)theFace->glyph->metrics.horiAdvance)/((double)theFace->units_per_EM);
                n_g.h_width=((double)theFace->glyph->metrics.width)/((double)theFace->units_per_EM);
            } else {
                n_g.h_width=n_g.h_advance=((double)(theFace->bbox.xMax-theFace->bbox.xMin))/((double)theFace->units_per_EM);
            }
            if ( FT_HAS_VERTICAL(theFace) ) {
                n_g.v_advance=((double)theFace->glyph->metrics.vertAdvance)/((double)theFace->units_per_EM);
                n_g.v_width=((double)theFace->glyph->metrics.height)/((double)theFace->units_per_EM);
            } else {
                n_g.v_width=n_g.v_advance=((double)theFace->height)/((double)theFace->units_per_EM);
            }
            if ( theFace->glyph->format == ft_glyph_format_outline ) {
                FT_Outline_Funcs ft2_outline_funcs = {
                    ft2_move_to,
                    ft2_line_to,
                    ft2_conic_to,
                    ft2_cubic_to,
                    0, 0
                };
                FT2GeomData user(path_builder, 1.0/((double)theFace->units_per_EM));
                FT_Outline_Decompose (&theFace->glyph->outline, &ft2_outline_funcs, &user);
            }
            doAdd=true;
        }
#endif
        path_builder.finish();

        if ( doAdd ) {
            Geom::PathVector pv = path_builder.peek();
            // close all paths
            for (Geom::PathVector::iterator i = pv.begin(); i != pv.end(); ++i) {
                i->close();
            }
            if ( !pv.empty() ) {
                n_g.pathvector = new Geom::PathVector(pv);
                Geom::OptRect bounds = bounds_exact(*n_g.pathvector);
                if (bounds) {
                    n_g.bbox[0] = bounds->left();
                    n_g.bbox[1] = bounds->top();
                    n_g.bbox[2] = bounds->right();
                    n_g.bbox[3] = bounds->bottom();
                }
            }
            glyphs[nbGlyph]=n_g;
            id_to_no[glyph_id]=nbGlyph;
            nbGlyph++;
        }
    } else {
    }
}