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

2014-11-24 09:13:54 · 作者: · 浏览: 6
}
{
// generate place information
WinDC* dcParameter=0;
if(resizeGlyphData)
{
glyphAdvances.Resize(glyphCount);
glyphOffsets.Resize(glyphCount);
}
while(true)
{
HRESULT hr=ScriptPlace(
(dcParameter dcParameter->GetHandle():NULL),
&scriptCache,
&glyphs[0],
glyphCount,
&glyphVisattrs[0],
&scriptItem->a,
&glyphAdvances[0],
&glyphOffsets[0],
&runAbc
);
if(hr==0)
{
break;
}
else if(hr==E_PENDING)
{
dcParameter=dc;
}
else
{
goto BUILD_UNISCRIBE_DATA_FAILED;
}
}
}

return true;
BUILD_UNISCRIBE_DATA_FAILED:
return false;
}
};

class ScriptRun : public Object
{
public:

DocumentFragment* documentFragment;
SCRIPT_ITEM* scriptItem;
int start;
int length;
const wchar_t* runText;

SCRIPT_CACHE scriptCache;
Array<SCRIPT_LOGATTR> charLogattrs;
int advance;
GlyphData wholeGlyph;
GlyphData tempGlyph;

ScriptRun()
:documentFragment(0)
,scriptItem(0)
,start(0)
,length(0)
,scriptCache(0)
,advance(0)
{
}

~ScriptRun()
{
ClearUniscribeData();
}

void ClearUniscribeData()
{
if(scriptCache)
{
ScriptFreeCache(&scriptCache);
scriptCache=0;
}
charLogattrs.Resize(0);
advance=0;
wholeGlyph.ClearUniscribeData(0, 0);
tempGlyph.ClearUniscribeData(0, 0);
}

bool BuildUniscribeData(WinDC* dc)
{
ClearUniscribeData();
{
// generate break information
charLogattrs.Resize(length);

HRESULT hr=ScriptBreak(
runText,
length,
&scriptItem->a,
&charLogattrs[0]
);
if(hr!=0)
{
goto BUILD_UNISCRIBE_DATA_FAILED;
}
}

dc->SetFont(documentFragment->fontObject);
if(!wholeGlyph.BuildUniscribeData(dc, documentFragment, scriptItem, scriptCache, runText, length))
{
goto BUILD_UNISCRIBE_DATA_FAILED;
}