Sign in to follow this  
kaush

Getting DirectWrite Direct2D Glyph's outline information

Recommended Posts

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]

Share this post


Link to post
Share on other sites
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 this post


Link to post
Share on other sites
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.

AddLines() for each line etc.

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

sorry for troubling you guys.

Share this post


Link to post
Share on other sites
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 this post


Link to post
Share on other sites
Quote:
Original post by treckle
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 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 this post


Link to post
Share on other sites
Quote:
Original post by treckle
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.



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 this post


Link to post
Share on other sites
Quote:
Original post by Anon Mike
What 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->glyphAdvances,
glyphRun->glyphOffsets,
glyphRun->glyphCount,
glyphRun->isSideways,
glyphRun->bidiLevel%2,
pSink
);



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

//Calls CallBack functions AddBezier(....) AddLines(....)
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.
please do if you know.

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

Share this post


Link to post
Share on other sites
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 this post


Link to post
Share on other sites
Quote:
Original post by Anon Mike
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.


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.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this