C++使用Uniscribe进行文字自动换行的计算和渲染(五)

2014-11-24 09:13:54 · 作者: · 浏览: 1

}

/***********************************************************************
ScriptFragment
***********************************************************************/

struct GlyphData
{
Array glyphs;
Array<SCRIPT_VISATTR> glyphVisattrs;
Array glyphAdvances;
Array glyphOffsets;
Array charCluster;
ABC runAbc;

GlyphData()
{
memset(&runAbc, 0, sizeof(runAbc));
}

void ClearUniscribeData(int glyphCount, int length)
{
glyphs.Resize(glyphCount);
glyphVisattrs.Resize(glyphCount);
glyphAdvances.Resize(glyphCount);
glyphOffsets.Resize(glyphCount);
charCluster.Resize(length);
memset(&runAbc, 0, sizeof(runAbc));
}

bool BuildUniscribeData(WinDC* dc, DocumentFragment* documentFragment, SCRIPT_ITEM* scriptItem, SCRIPT_CACHE& scriptCache, const wchar_t* runText, int length)
{
int glyphCount=glyphs.Count();
bool resizeGlyphData=false;
if(glyphCount==0)
{
glyphCount=(int)(1.5*length+16);
resizeGlyphData=true;
}
{
// generate shape information
WinDC* dcParameter=0;
if(resizeGlyphData)
{
glyphs.Resize(glyphCount);
glyphVisattrs.Resize(glyphCount);
charCluster.Resize(length);
}

while(true)
{
int availableGlyphCount=0;
HRESULT hr=ScriptShape(
(dcParameter dcParameter->GetHandle():NULL),
&scriptCache,
runText,
length,
glyphCount,
&scriptItem->a,
&glyphs[0],
&charCluster[0],
&glyphVisattrs[0],
&availableGlyphCount
);
if(hr==0)
{
glyphCount=availableGlyphCount;
break;
}
else if(hr==E_PENDING)
{
dcParameter=dc;
}
else if(hr==E_OUTOFMEMORY)
{
if(resizeGlyphData)
{
glyphCount+=length;
}
else
{
goto BUILD_UNISCRIBE_DATA_FAILED;
}
}
else
{
goto BUILD_UNISCRIBE_DATA_FAILED;
}
}
if(resizeGlyphData)
{
glyphs.Resize(glyphCount);
glyphVisattrs.Resize(glyphCount);
}