{
// 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;
}