# Getting DirectWrite Direct2D Glyph's outline information

## Recommended Posts

kaush    122
I want to retrieve the GLYPHs data in terms of bez knots, points etc. I uses the following concept to print or use the values of glyph. http://msdn.microsoft.com/en-us/library/ee453682%28VS.85%29.aspx Through this I can get compelete geometry of the point My question is how to get the data w.r.t. GLYPH. I mean if Text string is “AB” A Contains 2 contour. B Contains 3 contour. Then how can I know the printing data in Function AddBeziers(..) {} is of “A” or of “B” I need something which will indicate the starting of new GLYPH. /*In the above link I have changed a class DrawGlyph fucntion to get the geometry of glyph*/ CustomText_renderer::DrawGlyphRun(..Arguments..) { HRESULT hr = S_OK; //Create the path geometry ID2D1PathGeometry* pPathGeometry = NULL; hr = m_pD2DFactory->CreatePathGeometry(&pPathGeometry); ////Write to the path geometry using the sink ID2D1GeometrySink * pSink = NULL; if(SUCCEEDED(hr)) { hr = pPathGeometry->Open(&pSink); } /* Get the glyph run outline geometries back from DirectWrite and place them within the geometry sink.*/ if (SUCCEEDED(hr)) { hr = glyphRun->fontFace->GetGlyphRunOutline( glyphRun->fontEmSize, glyphRun->glyphIndices, glyphRun->glyphAdvances, glyphRun->glyphOffsets, glyphRun->glyphCount, glyphRun->isSideways, glyphRun->bidiLevel%2, pSink ); } // Close the geometry sink if (SUCCEEDED(hr)) { hr = pSink->Close(); } // Initialize a matrix to translate the origin of the glyph run. D2D1::Matrix3x2F const matrix = D2D1::Matrix3x2F( 1.0f, 0.0f, 0.0f, 1.0f, baselineOriginX, baselineOriginY); ID2D1SimplifiedGeometrySink * pSimplfiedSink = NULL; // SpecializedSink is class drived from ID2D1SimplifiedGeometrySink pSimplfiedSink = new SpecializedSink(); pPathGeometry->Simplify(D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES ,NULL ,pSimplfiedSink); /* Create the brush using the color pecified by our ColorDrawingEffect object.*/ if (SUCCEEDED(hr)) { hr = m_pRT->CreateSolidColorBrush( D2D1::ColorF(D2D1::ColorF::Black), &m_pOutLineBrush); } if (SUCCEEDED(hr)) { ID2D1TransformedGeometry* pTransformedGeometry = NULL; hr = m_pD2DFactory->CreateTransformedGeometry( pPathGeometry, &matrix, &pTransformedGeometry ); // Draw the outline of the glyph run m_pRT->DrawGeometry( pTransformedGeometry, m_pOutLineBrush ); } return hr; } Thankyou [Edited by - kaush on March 30, 2010 8:54:32 AM]

kaush    122

##### Share on other sites
Anon Mike    1098
GetGlyphRunOutline works on the entire run as a unit. There are no delimiters. If you want individual glyphs you need to call GetGlyphRunOutline for each one.

As for the geometry, maybe you could use ID2D1GeometryGroup?

##### Share on other sites
kaush    122
Q: Do anyone have sample or link to any sample in which we can run through each glyph separately in a string.

for example "EXAMPLE" has 7 glyphs, if i use ID2D1PathGeometry::Simplify()

it will call the callback function addbezier as per the flag sets and will complete the string in one single walk.

instead of using simplify() is there any function through which i can separately call addbezier for each E,X,A,M,P,L,E glyph.

In above question while calling ID2D1PathGeometry::simplify() it will callback the functions

String is "AB"

2 glyph

5 contour

BeginFigure() Start of each contour.

EndFigure() End of each contour.

AddBeziers() for each bezier points of counter.

The question is same again, how do i access data glypwise.

sorry for troubling you guys.

##### Share on other sites
treckle    100
With your "EXAMPLE" string, when you call Simplify, you should see the following calls back into your simplified geometry sink (in the following order):
    BeginFigure  // start of letter "E"    AddLines     // 11 points in the array - I'm using Tahoma font    EndFigure    // end of letter "E"    BeginFigure  // start of letter "X"    AddLines     // 11 points in the array    EndFigure    // end of letter "X"    BeginFigure  // start of letter "A"    AddLines     // 7 points in the array    EndFigure    // end of letter "A"    ...

The only problem with this method is that some glyphs (such as 'i' and 'j' have two figures). If you're doing all CAPS, you may be okay though.

[Edited by - treckle on April 27, 2010 5:19:15 PM]

##### Share on other sites
Anon Mike    1098
Quote:
 Original post by treckleThe only problem with this method is that some glyphs (such as 'i' and 'j' have two figures). If you're doing all CAPS, you may be okay though.

This isn't a problem. Glyphs are not the same thing as characters. The glyph id for 'A' probably isn't 65 (the ascii/Unicode character value). It's some font-specific value that you find by calling GetGlyphIndices. If a character has multiple forms than each form is a different glyph and will have a different id.

##### Share on other sites
kaush    122
Quote:
 Original post by treckleWith your "EXAMPLE" string, when you call Simplify, you should see the following calls back into your simplified geometry sink (in the following order): BeginFigure // start of letter "E" AddLines // 11 points in the array - I'm using Tahoma font EndFigure // end of letter "E" BeginFigure // start of letter "X" AddLines // 11 points in the array EndFigure // end of letter "X" BeginFigure // start of letter "A" AddLines // 7 points in the array EndFigure // end of letter "A" ...The only problem with this method is that some glyphs (such as 'i' and 'j' have two figures). If you're doing all CAPS, you may be okay though.

This problem is not specific to i,j.In CAPs letter A,B,R....kind of all character who has at least two contour considered to be same problem.

//Outer contour
BeginFigure // start of outer contour of "A"

AddLines // 7 points in the array

EndFigure // end of outer contour "A"

//inner contour
BeginFigure // start of inner contour "A"

AddLines // X points in the array

EndFigure // end of inner contour "A"

this is only specifying outer contour of "A". I mean for "A" call to Addlines will be two times, one for outer contour and one for inner contour.

we can't identify when the start of new Glyph[not contour] started. Because begin figure calls w.r.t. contour not for Glyph.

##### Share on other sites
Anon Mike    1098
What exactly is it that you don't understand about calling GetGlyphRunOutline one glyph at a time?

##### Share on other sites
kaush    122
Quote:
 Original post by Anon MikeWhat exactly is it that you don't understand about calling GetGlyphRunOutline one glyph at a time?

may be i am wrong, but need some help if you can.
what i did in "calling GetGlyphRunOutline one glyph at a time".
//The code
//The class inherited as CustomText_renderer : public IDWriteTextRenderer
//

//This function is being called from another class as callback.
//
CustomText_renderer::DrawGlyphRun(void* clientDrawingContext,
FLOAT baselineOriginX,
FLOAT baselineOriginY,
DWRITE_MEASURING_MODE measuringMode,
DWRITE_GLYPH_RUN const* glyphRun,
DWRITE_GLYPH_RUN_DESCRIPTION const* glyphRunDescription,
IUnknown* clientDrawingEffect)

{
HRESULT hr = S_OK;
ID2D1PathGeometry* pPathGeometry = NULL;
ID2D1GeometrySink * pSink = NULL;
ID2D1SimplifiedGeometrySink * pSimplfiedSink = NULL;

for(int iGlyphCntr = 0; iGlyphCntr <= glyphRun->glyphCount; ++iGlyphCntr)
{

if(SUCCEEDED(hr))
{
pSink = NULL;
pPathGeometry = NULL;
hr = m_pD2DFactory->CreatePathGeometry(&pPathGeometry);
hr = pPathGeometry->Open(&pSink);
}

hr = glyphRun->fontFace->GetGlyphRunOutline(
glyphRun->fontEmSize,
glyphRun->glyphIndices,
glyphRun->glyphOffsets,
glyphRun->glyphCount,
glyphRun->isSideways,
glyphRun->bidiLevel%2,
pSink
);

hr = pSink->Close();
pSimplfiedSink = NULL;
pSimplfiedSink = new SpecializedSink();

pPathGeometry->Simplify(D2D1_GEOMETRY_SIMPLIFICATION_OPTION_CUBICS_AND_LINES
,NULL
,pSimplfiedSink);
}

// thanks buddy i have skipped the code of transform and drawing geometry.

}

//i have solved it through above code.
//By solving means i have access the points of the glyph.

//Do anybody know better solution to extract the points of glyph.

[Edited by - kaush on May 3, 2010 4:28:53 AM]

##### Share on other sites
Anon Mike    1098
You're not even using iGlyphCntr. That code is calling GetGlyphRunOutline multiple times with the exact same data.

What you need is something like:
hr = glyphRun->fontFace->GetGlyphRunOutline(        glyphRun->fontEmSize,        glyphRun->glyphIndices + iGlyphCntr,  // current glyph        glyphRun->glyphAdvances + (glyphRun->glyphAdvances ? iGlyphCntr : 0),  // if glyphAdvances in NULL leave it that way        glyphRun->glyphOffsets + (glyphRun->glyphOffsets ? iGlyphCntr : 0),  // same        1,  // one glyph only        glyphRun->isSideways,        glyphRun->bidiLevel % 2,        pSink);

This will get the outline info for just one glyph. Do whatever you want with that info. Then move on to the next one.

##### Share on other sites
kaush    122
Quote:
 Original post by Anon MikeYou're not even using iGlyphCntr. That code is calling GetGlyphRunOutline multiple times with the exact same data.What you need is something like:hr = glyphRun->fontFace->GetGlyphRunOutline( glyphRun->fontEmSize, glyphRun->glyphIndices + iGlyphCntr, // current glyph glyphRun->glyphAdvances + (glyphRun->glyphAdvances ? iGlyphCntr : 0), // if glyphAdvances in NULL leave it that way glyphRun->glyphOffsets + (glyphRun->glyphOffsets ? iGlyphCntr : 0), // same 1, // one glyph only glyphRun->isSideways, glyphRun->bidiLevel % 2, pSink);This will get the outline info for just one glyph. Do whatever you want with that info. Then move on to the next one.

i am extremely sorry for my stupid mistake, i pasyted the wrong code while editing.
yes boss you are right i got the glyph data by same technique.
Now do we have better solution, because its very time consuming.