summaryrefslogtreecommitdiff
path: root/Build/source/libs/graphite-engine/src/segment
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/graphite-engine/src/segment')
-rw-r--r--Build/source/libs/graphite-engine/src/segment/FileInput.cpp2
-rw-r--r--Build/source/libs/graphite-engine/src/segment/FontCache.cpp17
-rw-r--r--Build/source/libs/graphite-engine/src/segment/FontCache.h5
-rw-r--r--Build/source/libs/graphite-engine/src/segment/FontFace.cpp259
-rw-r--r--Build/source/libs/graphite-engine/src/segment/FontFace.h26
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrCharStream.h2
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrClassTable.h2
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrEngine.cpp46
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrEngine.h49
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrFSM.cpp38
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrFSM.h7
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrFeature.cpp1
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrGlyphTable.h49
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrPass.cpp22
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrPass.h33
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrPassActionCode.cpp7
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrSlotState.cpp301
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrSlotState.h604
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrSlotStream.cpp2
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrSlotStream.h1
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrTableManager.cpp80
-rw-r--r--Build/source/libs/graphite-engine/src/segment/GrTableManager.h5
-rw-r--r--Build/source/libs/graphite-engine/src/segment/Main.h13
-rw-r--r--Build/source/libs/graphite-engine/src/segment/Makefile.am2
-rw-r--r--Build/source/libs/graphite-engine/src/segment/MemoryUsage.cpp780
-rw-r--r--Build/source/libs/graphite-engine/src/segment/Segment.cpp425
-rw-r--r--Build/source/libs/graphite-engine/src/segment/SegmentAux.cpp35
-rw-r--r--Build/source/libs/graphite-engine/src/segment/TransductionLog.cpp25
-rw-r--r--Build/source/libs/graphite-engine/src/segment/explicit_instantiations.cpp44
29 files changed, 2063 insertions, 819 deletions
diff --git a/Build/source/libs/graphite-engine/src/segment/FileInput.cpp b/Build/source/libs/graphite-engine/src/segment/FileInput.cpp
index abd4fb800c3..52969532cd3 100644
--- a/Build/source/libs/graphite-engine/src/segment/FileInput.cpp
+++ b/Build/source/libs/graphite-engine/src/segment/FileInput.cpp
@@ -98,7 +98,7 @@ bool GrBufferIStream::OpenBuffer(byte * pbBuffer, int cb)
m_pbStart = pbBuffer;
m_pbNext = pbBuffer;
- if (cb >= 0)
+ if (cb > 0)
m_pbLim = m_pbStart + cb;
// otherwise we don't know the length
diff --git a/Build/source/libs/graphite-engine/src/segment/FontCache.cpp b/Build/source/libs/graphite-engine/src/segment/FontCache.cpp
index 041f449a401..f0540463e3b 100644
--- a/Build/source/libs/graphite-engine/src/segment/FontCache.cpp
+++ b/Build/source/libs/graphite-engine/src/segment/FontCache.cpp
@@ -171,11 +171,9 @@ bool FontCache::RemoveFontFace(std::wstring strFaceName, bool fBold, bool fItali
Assert(m_cfface >= 0);
- if (m_cfface <= 0 && m_flush == kflushAuto && fZapCache)
+ if (m_flush == kflushAuto && fZapCache)
{
- // All items are NULL; delete this cache. Probably this is because
- // the program is exiting.
- FontFace::ZapFontCache();
+ DeleteIfEmpty();
}
return fPrevVal;
@@ -250,6 +248,17 @@ void FontCache::InsertCacheItem(int ifci)
}
/*----------------------------------------------------------------------------------------------
+ Delete the cache if it is empty.
+----------------------------------------------------------------------------------------------*/
+void FontCache::DeleteIfEmpty()
+{
+ if (m_cfface <= 0)
+ // All items are NULL; delete this cache. Probably this is because
+ // the program is exiting.
+ FontFace::ZapFontCache();
+}
+
+/*----------------------------------------------------------------------------------------------
Check that the cache is indeed empty.
----------------------------------------------------------------------------------------------*/
void FontCache::AssertEmpty()
diff --git a/Build/source/libs/graphite-engine/src/segment/FontCache.h b/Build/source/libs/graphite-engine/src/segment/FontCache.h
index 7159ea35d98..56da5ab26b8 100644
--- a/Build/source/libs/graphite-engine/src/segment/FontCache.h
+++ b/Build/source/libs/graphite-engine/src/segment/FontCache.h
@@ -24,11 +24,13 @@ namespace gr
{
class FontFace;
+class FontMemoryUsage;
/*----------------------------------------------------------------------------------------------
TODO: change from a sorted list to a hash table, if performance so requires.
----------------------------------------------------------------------------------------------*/
class FontCache {
+ friend class FontMemoryUsage;
public:
FontCache()
@@ -69,6 +71,7 @@ public:
void GetFontFace(std::wstring strFaceName, bool fBold, bool fItalic, FontFace ** ppfface);
void CacheFontFace(std::wstring strFaceName, bool fBold, bool fItalic, FontFace * pfface);
bool RemoveFontFace(std::wstring strFaceName, bool fBold, bool fItalic, bool fZapCache = true);
+ void DeleteIfEmpty();
void AssertEmpty();
int GetFlushMode()
@@ -80,6 +83,8 @@ public:
// Debugging:
//bool DbgCheckFontCache();
+ void calculateMemoryUsage(FontMemoryUsage & fmu);
+
protected:
int FindCacheItem(std::wstring strFaceName);
void InsertCacheItem(int ifci);
diff --git a/Build/source/libs/graphite-engine/src/segment/FontFace.cpp b/Build/source/libs/graphite-engine/src/segment/FontFace.cpp
index 838685ebc65..45461fe63ac 100644
--- a/Build/source/libs/graphite-engine/src/segment/FontFace.cpp
+++ b/Build/source/libs/graphite-engine/src/segment/FontFace.cpp
@@ -47,7 +47,8 @@ FontCache * FontFace::s_pFontCache = 0;
Called from the font constructor.
----------------------------------------------------------------------------------------------*/
FontFace * FontFace::GetFontFace(Font * pfont,
- std::wstring strFaceName, bool fBold, bool fItalic)
+ std::wstring strFaceName, bool fBold, bool fItalic,
+ bool fDumbFallback)
{
if (s_pFontCache == NULL)
s_pFontCache = new FontCache;
@@ -59,7 +60,7 @@ FontFace * FontFace::GetFontFace(Font * pfont,
// Create a new font face.
pfface = new FontFace();
- pfface->InitFontFace(pfont, strFaceName, fBold, fItalic);
+ pfface->InitFontFace(pfont, strFaceName, fBold, fItalic, fDumbFallback);
return pfface;
}
@@ -67,7 +68,8 @@ FontFace * FontFace::GetFontFace(Font * pfont,
Initialize the engine using the given Graphite font.
----------------------------------------------------------------------------------------------*/
GrResult FontFace::InitFontFace(Font * pfont,
- std::wstring stuFaceName, bool fBold, bool fItalic)
+ std::wstring stuFaceName, bool fBold, bool fItalic,
+ bool fDumbFallback)
{
AssertPtrN(pfont);
@@ -96,20 +98,42 @@ GrResult FontFace::InitFontFace(Font * pfont,
// res = InitFromControlFile(pfont, stuFaceName.c_str(), fBold, fItalic);
//#endif // GR_FW
- //if (ResultFailed(res))
- //{
-
-
// Read directly from the font.
m_pgreng->DestroyContents();
- GrResult res = m_pgreng->ReadFontTables(pfont, fItalic);
-
- //}
+ GrResult res = kresUnexpected;
+ try {
+ res = m_pgreng->ReadFontTables(pfont, fItalic);
+ }
+ catch (...)
+ {
+ if (fDumbFallback && m_pgreng->DumbFallback() && !m_pgreng->BadFont())
+ {
+ // If we have a basically good font but can't do Graphite,
+ // just go with empty tables, which should be set up.
+ res = m_pgreng->m_resFontRead;
+ }
+ else
+ {
+ if (m_cfonts == 0)
+ {
+ //s_pFontCache->DeleteIfEmpty();
+ //Assert(s_pFontCache == 0);
+ delete this; // will also delete GrEngine
+ }
+ else
+ {
+ delete m_pgreng;
+ }
+ m_pgreng = NULL;
+ throw; // throw original exception
+ }
+ }
m_pgreng->m_resFontValid = res;
m_pgreng->m_fBold = fBold;
m_pgreng->m_fItalic = fItalic;
+
s_pFontCache->CacheFontFace(m_pgreng->FaceName(), fBold, fItalic, this);
return m_pgreng->m_resFontValid;
@@ -120,9 +144,11 @@ GrResult FontFace::InitFontFace(Font * pfont,
device.
@return A GrResult indicating whether we were successful in loading the Graphite font:
- kresOk means success, kresFail means the Graphite font could not be found,
- kresUnexpected means the Graphite tables could not be loaded; kresFalse means it is
- not a Graphite font at all (has no Silf table).
+ - kresOk means success
+ - kresFail means the Graphite font could not be found or the basic font tables
+ (head, name, cmap) could not be loaded
+ - kresUnexpected means the Graphite tables could not be loaded
+ - kresFalse means it is not a Graphite font at all (has no Silf table).
----------------------------------------------------------------------------------------------*/
GrResult GrEngine::ReadFontTables(Font * pfont, bool fItalic)
{
@@ -136,12 +162,15 @@ GrResult GrEngine::ReadFontTables(Font * pfont, bool fItalic)
bool fOk = false;
- const void * pHeadTbl; const void * pCmapTbl; const void * pSileTbl; const void * pSilfTbl;
- const void * pFeatTbl; const void * pGlatTbl; const void * pGlocTbl; const void * pNameTbl; const void * pSillTbl;
- size_t cbHeadSz, cbCmapSz, /*cbSileSz,*/ cbSilfSz, cbFeatSz, cbGlatSz, cbGlocSz, cbNameSz, cbSillSz;
+ const void * pHeadTbl; const void * pSileTbl; const void * pSilfTbl;
+ const void * pFeatTbl; const void * pGlatTbl; const void * pGlocTbl; const void * pSillTbl;
+ //const void * pCmapTbl; const void * pNameTbl;
+ size_t cbHeadSz, cbSilfSz, cbFeatSz, cbGlatSz, cbGlocSz, cbSillSz;
+ //size_t cbCmapSz, cbSileSz, cbNameSz;
m_fFakeItalic = false;
+ bool fBasicTables = false;
bool fSilf = false; // does the font have some sort of Silf table?
int nCheckSum = 0;
@@ -199,7 +228,7 @@ GrResult GrEngine::ReadFontTables(Font * pfont, bool fItalic)
//if (pSileTbl)
//{
// pgg->get_FontCharProperties(&chrpOriginal);
- // grstrm.OpenBuffer(sile_tbl, sile_tbl.size());
+ // grstrm.OpenBuffer(pSileTbl, sile_tbl.size());
// m_fUseSepBase = ReadSileTable(pgg, grstrm, 0, &m_mFontEmUnits, &fMismatchedBase);
// grstrm.Close();
@@ -216,64 +245,21 @@ GrResult GrEngine::ReadFontTables(Font * pfont, bool fItalic)
// We don't need the offset table, and there's no way to get it anyway
// without a font file.
- // cmap
- res = (pCmapTbl = pfont->getTable(TtfUtil::TableIdTag(ktiCmap), &cbCmapSz)) ? kresOk : kresFail;
- fOk = pCmapTbl && (cbCmapSz == 0 || TtfUtil::CheckTable(ktiCmap, pCmapTbl, cbCmapSz));
+ // cmap and name
+ Assert(!m_fCmapTblCopy);
+ Assert(!m_fNameTblCopy);
+ fOk = SetCmapAndNameTables(pfont);
if (!fOk)
{
- m_stuInitError = L"could not locate cmap table";
- m_ferr = kferrFindCmapTable;
- ReturnResult(kresFail);
+ goto LUnexpected;
}
- // Make a private copy of the cmap for the engine's use.
- m_pCmapTbl = new byte[cbCmapSz];
- std::copy(reinterpret_cast<const byte*>(pCmapTbl),
- reinterpret_cast<const byte*>(pCmapTbl) + cbCmapSz, m_pCmapTbl);
-
- // MS Unicode cmap
- m_pCmap_3_1 = TtfUtil::FindCmapSubtable(m_pCmapTbl, 3, 1);
- m_pCmap_3_10 = TtfUtil::FindCmapSubtable(m_pCmapTbl, 3, 10);
- if (!m_pCmap_3_1)
- m_pCmap_3_1 = TtfUtil::FindCmapSubtable(m_pCmapTbl, 3, 0);
- if (!m_pCmap_3_1)
- {
- m_stuInitError = L"failure to load cmap subtable";
- m_ferr = kferrLoadCmapSubtable;
- ReturnResult(kresFail);
- }
- if (!TtfUtil::CheckCmap31Subtable(m_pCmap_3_1))
- {
- m_stuInitError = L"checking cmap subtable failed";
- m_ferr = kferrCheckCmapSubtable;
- ReturnResult(kresFail);
- }
+ fBasicTables = true;
// If we have a bad base file, don't do Graphite stuff.
if (fBadBase || fMismatchedBase)
goto LUnexpected;
- // name
-
- // Currently the only stuff we're getting from the name table are our feature names,
- // so use the version from the Graphite font (not the base font if any).
- //////if (m_fUseSepBase)
- ////// pgg->SetupGraphics(&chrpOriginal);
-
- // name - need feature names later
- res = (pNameTbl = (byte *)pfont->getTable(TtfUtil::TableIdTag(ktiName), &cbNameSz)) ? kresOk : kresFail;
- fOk = pNameTbl && (cbNameSz == 0 || TtfUtil::CheckTable(ktiName, pNameTbl, cbNameSz));
- if (!fOk)
- {
- m_stuInitError = L"could not locate name table";
- m_ferr = kferrFindNameTable;
- ReturnResult(kresFail);
- }
- // Make a private copy of the name table for the engine's use.
- m_pNameTbl = new byte[cbNameSz];
- std::copy(reinterpret_cast<const byte*>(pNameTbl),
- reinterpret_cast<const byte*>(pNameTbl) + cbNameSz, m_pNameTbl);
-
/****
Obtain font name from InitNew() now instead of reading from font file. InitNew should
should have a correct font name passed to it since it should come from a font registered
@@ -360,13 +346,27 @@ GrResult GrEngine::ReadFontTables(Font * pfont, bool fItalic)
&m_fxdBadVersion);
if (!fOk)
{
- wchar_t rgch[20];
- swprintf(rgch, 20, L"%d", m_fxdBadVersion >> 16);
+// wchar_t rgch1[50];
+// wchar_t rgch2[50];
+//#if defined(_WIN32)
+// // This version does not work in Windows, in spite of being documented:
+// // swprintf(rgch, 50, L"%d", (m_fxdBadVersion >> 16));
+// // Removing the size argument make it work.
+// swprintf(rgch1, L"%d", (m_fxdBadVersion >> 16));
+// swprintf(rgch2, L"%d", (m_fxdBadVersion & 0x0000FFFF));
+//#else
+// swprintf(rgch1, 50, L"%d", (m_fxdBadVersion >> 16));
+// swprintf(rgch2, 50, L"%d", (m_fxdBadVersion & 0x0000FFFF));
+//#endif
+ char rgch[50]; // more than enough space to print two 16-bit ints
+ char *pch = &rgch[0];
+ sprintf(rgch, "%d.%d", (m_fxdBadVersion >> 16), (m_fxdBadVersion & 0x0000FFFF));
std::wstring stu = L"unsupported version (";
- stu.append(rgch);
- swprintf(rgch, 20, L"%d", m_fxdBadVersion & 0x0000FFFF);
- stu.append(L".");
- stu.append(rgch);
+ //stu.append(rgch1);
+ //stu.append(L".");
+ //stu.append(rgch2);
+ while (*pch != 0)
+ stu.push_back((wchar_t)*pch++);
stu.append(L") of Graphite tables");
m_stuInitError.assign(stu.c_str());
m_ferr = kferrBadVersion;
@@ -461,7 +461,12 @@ LUnexpected:
CreateEmpty();
m_nFontCheckSum = nCheckSum;
- m_resFontRead = (fSilf) ? kresUnexpected : kresFalse;
+ if (!fBasicTables)
+ m_resFontRead = kresFail; // bad font
+ else if (!fSilf)
+ m_resFontRead = kresFalse; // no Silf table--not a Graphite font
+ else
+ m_resFontRead = kresUnexpected; // couldn't read the Graphite tables
fexptn.errorCode = m_ferr;
fexptn.version = m_fxdBadVersion >> 16;
@@ -471,6 +476,113 @@ LUnexpected:
ReturnResult(m_resFontRead);
}
+/*----------------------------------------------------------------------------------------------
+ Read the cmap and name tables.
+
+ This is called from two places. One is when we first initialize the engine. Also, if the
+ font tables have not been actually copied from the font, they may have been deleted
+ when the font was deleted. So when reusing the engine, set them to something valid based
+ on the current font.
+----------------------------------------------------------------------------------------------*/
+bool GrEngine::SetCmapAndNameTables(Font * pfont)
+{
+ GrResult res = kresOk;
+ bool fOk;
+ const void * pCmapTbl;
+ const void * pNameTbl;
+ size_t cbCmapSz, cbNameSz;
+
+ // cmap
+ if (!m_fCmapTblCopy)
+ {
+ res = (pCmapTbl = pfont->getTable(TtfUtil::TableIdTag(ktiCmap), &cbCmapSz)) ? kresOk : kresFail;
+ fOk = pCmapTbl && (cbCmapSz == 0 || TtfUtil::CheckTable(ktiCmap, pCmapTbl, cbCmapSz));
+ if (!fOk)
+ {
+ m_stuInitError = L"could not locate cmap table";
+ m_ferr = kferrFindCmapTable;
+ return false;
+ }
+
+ if (pCmapTbl && cbCmapSz > 0)
+ {
+ // Make a private copy of the cmap for the engine's use.
+ m_pCmapTbl = new byte[cbCmapSz];
+ std::copy(reinterpret_cast<const byte*>(pCmapTbl),
+ reinterpret_cast<const byte*>(pCmapTbl) + cbCmapSz, m_pCmapTbl);
+ m_fCmapTblCopy = true;
+ m_cbCmapTbl = cbCmapSz;
+ }
+ else
+ {
+ m_pCmapTbl = const_cast<byte*>(reinterpret_cast<const byte*>(pCmapTbl));
+ m_fCmapTblCopy = false;
+ }
+
+ // MS Unicode cmap
+ m_pCmap_3_1 = TtfUtil::FindCmapSubtable(m_pCmapTbl, 3, 1);
+ m_pCmap_3_10 = TtfUtil::FindCmapSubtable(m_pCmapTbl, 3, 10);
+ if (!m_pCmap_3_1)
+ m_pCmap_3_1 = TtfUtil::FindCmapSubtable(m_pCmapTbl, 3, 0);
+ if (!m_pCmap_3_1)
+ {
+ m_stuInitError = L"failure to load cmap subtable";
+ m_ferr = kferrLoadCmapSubtable;
+ return false;
+ }
+ if (!TtfUtil::CheckCmap31Subtable(m_pCmap_3_1))
+ {
+ m_stuInitError = L"checking cmap subtable failed";
+ m_ferr = kferrCheckCmapSubtable;
+ return false;
+ }
+ }
+ else
+ {
+ Assert(m_pCmapTbl);
+ }
+
+ // name table - eventually need feature label strings
+
+ // Currently the only stuff we're getting from the name table are our feature names,
+ // so use the version from the Graphite font (not the base font if any).
+ //////if (m_fUseSepBase)
+ ////// pgg->SetupGraphics(&chrpOriginal);
+
+ if (!m_fNameTblCopy)
+ {
+ res = (pNameTbl = (byte *)pfont->getTable(TtfUtil::TableIdTag(ktiName), &cbNameSz)) ? kresOk : kresFail;
+ fOk = pNameTbl && (cbNameSz == 0 || TtfUtil::CheckTable(ktiName, pNameTbl, cbNameSz));
+ if (!fOk)
+ {
+ m_stuInitError = L"could not locate name table";
+ m_ferr = kferrFindNameTable;
+ return false;
+ }
+
+ if (pNameTbl && cbNameSz > 0)
+ {
+ // Make a private copy of the name table for the engine's use.
+ m_pNameTbl = new byte[cbNameSz];
+ std::copy(reinterpret_cast<const byte*>(pNameTbl),
+ reinterpret_cast<const byte*>(pNameTbl) + cbNameSz, m_pNameTbl);
+ m_fNameTblCopy = true;
+ m_cbNameTbl = cbNameSz;
+ }
+ else
+ {
+ m_pNameTbl = const_cast<byte*>(reinterpret_cast<const byte*>(pNameTbl));
+ m_fNameTblCopy = false;
+ }
+ }
+ else
+ {
+ Assert(m_pNameTbl);
+ }
+
+ return true;
+}
+
//void FontFace::DbgCheckFontFace()
//{
@@ -481,7 +593,6 @@ LUnexpected:
// Assert(chw0 <= 0x007A); // z
//}
-
} // namespace gr
//:End Ignore
diff --git a/Build/source/libs/graphite-engine/src/segment/FontFace.h b/Build/source/libs/graphite-engine/src/segment/FontFace.h
index 70be57d5cd2..7f2684a5908 100644
--- a/Build/source/libs/graphite-engine/src/segment/FontFace.h
+++ b/Build/source/libs/graphite-engine/src/segment/FontFace.h
@@ -44,6 +44,8 @@ class Segment;
----------------------------------------------------------------------------------------------*/
class FontFace
{
+ friend class gr::FontMemoryUsage;
+
public:
FontFace()
{
@@ -52,7 +54,8 @@ public:
~FontFace()
{
- s_pFontCache->RemoveFontFace(m_pgreng->FaceName(), m_pgreng->Bold(), m_pgreng->Italic());
+ if (s_pFontCache)
+ s_pFontCache->RemoveFontFace(m_pgreng->FaceName(), m_pgreng->Bold(), m_pgreng->Italic());
delete m_pgreng;
}
@@ -63,7 +66,7 @@ public:
void DecFontCount()
{
m_cfonts--;
- if (m_cfonts <= 0 && s_pFontCache->GetFlushMode() == kflushAuto)
+ if (m_cfonts <= 0 && (s_pFontCache == NULL || s_pFontCache->GetFlushMode() == kflushAuto))
delete this;
}
@@ -73,10 +76,12 @@ public:
}
static FontFace * GetFontFace(Font * pfont,
- std::wstring strFaceName, bool fBold, bool fItalic);
+ std::wstring strFaceName, bool fBold, bool fItalic,
+ bool fDumbFallback = false);
GrResult InitFontFace(Font * pfont,
- std::wstring stuFaceName, bool fBold, bool fItalic);
+ std::wstring stuFaceName, bool fBold, bool fItalic,
+ bool fDumbLayout);
FontErrorCode IsValidForGraphite(int * pnVersion, int * pnSubVersion)
{
@@ -172,6 +177,16 @@ public:
m_pgreng->get_ScriptDirection(&script_dirs, &err_dummy, 1);
return ScriptDirCode(script_dirs);
}
+
+ bool BadFont(FontErrorCode * pferr = NULL)
+ {
+ return m_pgreng->BadFont(pferr);
+ }
+ bool DumbFallback(FontErrorCode * pferr = NULL)
+ {
+ return m_pgreng->DumbFallback(pferr);
+ }
+
public:
// For use in segment creation:
void RenderLineFillSegment(Segment * pseg, Font * pfont, ITextSource * pts,
@@ -206,6 +221,9 @@ public:
//}
//void DbgCheckFontFace();
+ static void calculateAllMemoryUsage(FontMemoryUsage & fmu);
+ void calculateMemoryUsage(FontMemoryUsage & fmu);
+
protected:
// Number of fonts in existence that use this face; when it goes to zero, delete.
int m_cfonts;
diff --git a/Build/source/libs/graphite-engine/src/segment/GrCharStream.h b/Build/source/libs/graphite-engine/src/segment/GrCharStream.h
index 7a49b8fa030..fa9d8b40785 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrCharStream.h
+++ b/Build/source/libs/graphite-engine/src/segment/GrCharStream.h
@@ -42,7 +42,7 @@ public:
}
// Getters:
- ITextSource * String() { return m_pgts; }
+ ITextSource * TextSrc() { return m_pgts; }
int Min() { return m_ichrMin; }
int Pos() { return m_ichrPos; }
int Lim() { return m_ichrLim; }
diff --git a/Build/source/libs/graphite-engine/src/segment/GrClassTable.h b/Build/source/libs/graphite-engine/src/segment/GrClassTable.h
index 5677fdfd21b..67d6940862c 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrClassTable.h
+++ b/Build/source/libs/graphite-engine/src/segment/GrClassTable.h
@@ -110,6 +110,8 @@ protected:
class GrClassTable
{
+ friend class FontMemoryUsage;
+
public:
// Constructor & destructor:
GrClassTable()
diff --git a/Build/source/libs/graphite-engine/src/segment/GrEngine.cpp b/Build/source/libs/graphite-engine/src/segment/GrEngine.cpp
index d7c2aaf320c..62a33b6a4ed 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrEngine.cpp
+++ b/Build/source/libs/graphite-engine/src/segment/GrEngine.cpp
@@ -119,6 +119,8 @@ void GrEngine::BasicInit()
// new interface stuff:
m_pCmapTbl = NULL;
m_pNameTbl = NULL;
+ m_fCmapTblCopy = false;
+ m_fNameTblCopy = false;
m_fLogXductn = false;
@@ -203,10 +205,14 @@ void GrEngine::DestroyContents(bool fDestroyCmap)
m_pCmap_3_1 = NULL;
m_pCmap_3_10 = NULL;
- delete[] m_pCmapTbl;
- delete[] m_pNameTbl;
+ if (m_fCmapTblCopy)
+ delete[] m_pCmapTbl;
+ if (m_fNameTblCopy)
+ delete[] m_pNameTbl;
m_pCmapTbl = NULL;
m_pNameTbl = NULL;
+ m_fCmapTblCopy = false;
+ m_fNameTblCopy = false;
}
delete m_ptman;
@@ -573,6 +579,8 @@ void GrEngine::MakeSegment(
// Uninitialized.
return; // ReturnResult(kresUnexpected);
+ SetCmapAndNameTables(pfont);
+
int segmode = ksegmodeRange; // segment from range
if (fJust)
segmode = ksegmodeJust; // justified segment
@@ -597,7 +605,9 @@ void GrEngine::MakeSegment(
// Find the end of the range to render with the current font.
int nDirDepth;
- int ichFontLim, ichStrmLim, ichSegLim;
+ int ichFontLim;
+ int ichStrmLim = 0;
+ int ichSegLim = 0;
switch (segmode)
{
case ksegmodeBreak: // find break point
@@ -653,9 +663,9 @@ void GrEngine::MakeSegment(
// Run the tables and get back a segment.
- bool fMoreText;
- int ichCallerBtLim;
- bool fInfiniteWidth;
+ bool fMoreText = false;
+ int ichCallerBtLim = -1;
+ bool fInfiniteWidth = false;
switch (segmode)
{
//case ksegmodeMms:
@@ -886,26 +896,26 @@ int GrEngine::FindFontLim(ITextSource * pgts, int ichwMinFont, int * pnDirDepth)
implementation of the engine can't handle.
----------------------------------------------------------------------------------------------*/
bool GrEngine::CheckTableVersions(GrIStream * pgrstrm,
- byte *silf_tbl, int lSilfStart,
- byte *gloc_tbl, int lGlocStart,
- byte *feat_tbl, int lFeatStart,
+ byte *pSilfTbl, int lSilfStart,
+ byte *pGlobTbl, int lGlocStart,
+ byte *pFeatTbl, int lFeatStart,
int * pfxdBadVersion)
{
- pgrstrm->OpenBuffer(silf_tbl, isizeof(int));
+ pgrstrm->OpenBuffer(pSilfTbl, isizeof(int));
pgrstrm->SetPositionInFont(lSilfStart);
*pfxdBadVersion = ReadVersion(*pgrstrm);
pgrstrm->CloseBuffer();
if (*pfxdBadVersion > kSilfVersion)
return false;
- pgrstrm->OpenBuffer(gloc_tbl, lGlocStart + isizeof(int));
+ pgrstrm->OpenBuffer(pGlobTbl, lGlocStart + isizeof(int));
pgrstrm->SetPositionInFont(lGlocStart);
*pfxdBadVersion = ReadVersion(*pgrstrm);
pgrstrm->CloseBuffer();
if (*pfxdBadVersion > kGlocVersion)
return false;
- pgrstrm->OpenBuffer(feat_tbl, isizeof(int));
+ pgrstrm->OpenBuffer(pFeatTbl, isizeof(int));
pgrstrm->SetPositionInFont(lFeatStart);
*pfxdBadVersion = ReadVersion(*pgrstrm);
pgrstrm->CloseBuffer();
@@ -1062,7 +1072,7 @@ bool GrEngine::ReadSilfTable(GrIStream & grstrm, long lTableStart, int iSubTable
data16 chwTmp;
*pchwMaxGlyphID = grstrm.ReadUShortFromFont();
- // extra ascent
+ // extra ascent and descent
m_mXAscent = grstrm.ReadShortFromFont();
m_mXDescent = grstrm.ReadShortFromFont();
@@ -1111,9 +1121,9 @@ bool GrEngine::ReadSilfTable(GrIStream & grstrm, long lTableStart, int iSubTable
bTmp = grstrm.ReadByteFromFont();
m_chwDirAttr = bTmp;
- // Sanity checks.
- if (m_chwPseudoAttr > 100 || m_chwBWAttr > 100 || m_chwDirAttr > 100)
- return false; // bad table
+ // Sanity checks--don't bother with these, I don't seem to be able to know what are reasonable values.
+ //if (m_chwPseudoAttr > 200 || m_chwBWAttr > 200 || m_chwDirAttr > 200)
+ // return false; // bad table
if (*pfxdSilfVersion >= 0x00020000)
{
@@ -1824,7 +1834,7 @@ void GrEngine::InitSlot(GrSlotState * pslot, int nUnicode)
LDefaults:
// Otherwise, in fill defaults for some basic values.
- if (pslot->BreakWeight() == GrSlotState::kNotYetSet)
+ if (pslot->BreakWeight() == GrSlotState::kNotYetSet8)
{
switch (nUnicode)
{
@@ -1839,7 +1849,7 @@ LDefaults:
}
}
- if ((int)pslot->Directionality() == GrSlotState::kNotYetSet)
+ if ((int)pslot->Directionality() == GrSlotState::kNotYetSet8)
{
switch (nUnicode)
{
diff --git a/Build/source/libs/graphite-engine/src/segment/GrEngine.h b/Build/source/libs/graphite-engine/src/segment/GrEngine.h
index ee7d8de0e77..81b54e805bc 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrEngine.h
+++ b/Build/source/libs/graphite-engine/src/segment/GrEngine.h
@@ -43,6 +43,7 @@ class Segment;
class GrEngine : public GraphiteProcess
{
friend class FontFace;
+ friend class FontMemoryUsage;
public:
// Constructors & destructors:
@@ -405,14 +406,16 @@ protected:
// control file
GrResult m_resFontRead; // kresOk if the Graphite font was loaded successfully;
- // kresFail if the Graphite font could not be found;
+ // kresFail if the font could not be found or basic tables couldn't be read;
+ // kresFalse if the Silf table is not present;
// kresUnexpected if the Graphite tables could not be loaded
- GrResult m_resFontValid; // kresOk if Graphite font & dc font match cmaps
- // kresUnexpected if dumb rendering
- // kresFail if dumb rendering with no cmap
- // kresInvalidArg if the engine is not yet initialized
-
+ GrResult m_resFontValid; // kresInvalidArg if the engine is not yet initialized
+ // Originally:
+ // kresOk if Graphite font & dc font match cmaps
+ // kresUnexpected/kresFalse if dumb rendering
+ // kresFail if dumb rendering with no cmap
+ // But now it is apparently just = to m_resFontRead otherwise.
FontErrorCode m_ferr;
int m_fxdBadVersion;
@@ -475,14 +478,14 @@ protected:
int m_mFontEmUnits; // number of design units in the Em square for the font
// for pseudo-glyph mappings
- int m_cpsd; // number of psuedo-glyphs
- GrPseudoMap * m_prgpsd;
- int m_dipsdInit; // (max power of 2 <= m_cpsd);
- // size of initial range to consider
- int m_cPsdLoop; // log2(max power of 2 <= m_cpsd);
- // indicates how many iterations are necessary
- int m_ipsdStart; // m_cpsd - m_dipsdInit;
- // where to start search
+ int m_cpsd; // number of psuedo-glyphs
+ GrPseudoMap * m_prgpsd;
+ int m_dipsdInit; // (max power of 2 <= m_cpsd);
+ // size of initial range to consider
+ int m_cPsdLoop; // log2(max power of 2 <= m_cpsd);
+ // indicates how many iterations are necessary
+ int m_ipsdStart; // m_cpsd - m_dipsdInit;
+ // where to start search
// for Unicode to glyph ID mapping
////TableBuffer m_tbufCmap; // hold the full cmap table
@@ -491,10 +494,14 @@ protected:
// use for Unicode to Glyph ID conversion
void * m_pCmap_3_10;
byte * m_pCmapTbl;
+ bool m_fCmapTblCopy;
+ int m_cbCmapTbl; // needed only for memory instrumentation
// for feature names and maybe other strings from font later
////TableBuffer m_tbufNameTbl; // hold full name table; use Name() method to access
byte * m_pNameTbl;
+ bool m_fNameTblCopy;
+ int m_cbNameTbl; // needed only for memory instrumentation
bool m_fLogXductn; // true if we want to log the transduction process
@@ -546,9 +553,23 @@ protected:
int chwMaxGlyphID, int fxdSilfVersion);
bool ReadFeatTable(GrIStream & grstrm, long lTableStart);
bool ReadSillTable(GrIStream & grstrm, long lTableStart);
+ bool SetCmapAndNameTables(Font * pfont);
void CreateEmpty();
+ bool BadFont(FontErrorCode * pferr = NULL)
+ {
+ if (pferr)
+ *pferr = m_ferr;
+ return (m_resFontValid == kresFail || m_resFontRead == kresFail);
+ }
+ bool DumbFallback(FontErrorCode * pferr = NULL)
+ {
+ if (pferr)
+ *pferr = m_ferr;
+ return (m_resFontValid != kresOk || m_resFontRead != kresOk);
+ }
+
gid16 MapToPseudo(int nUnicode);
// NEW interface
diff --git a/Build/source/libs/graphite-engine/src/segment/GrFSM.cpp b/Build/source/libs/graphite-engine/src/segment/GrFSM.cpp
index bd4d13a24d0..c36670c9634 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrFSM.cpp
+++ b/Build/source/libs/graphite-engine/src/segment/GrFSM.cpp
@@ -102,8 +102,8 @@ bool GrFSM::ReadFromFont(GrIStream & grstrm, int fxdVersion)
// rules in the pass; some rules may be listed multiply, if they are matched by more
// than one state.
int crulInMap = m_prgirulnMin[crowSuccess];
-
m_prgrulnMatched = new data16[crulInMap];
+ m_crulnMatched = crulInMap;
pchw = m_prgrulnMatched;
for (i = 0; i < crulInMap; i++, pchw++)
{
@@ -167,7 +167,7 @@ int GrFSM::GetRuleToApply(GrTableManager * ptman, GrPass * ppass,
int prgcslotMatched[kMaxSlotsPerRule];
// Run the transition table until it jams.
- int crowAccepting = RunTransitionTable(psstrmIn, psstrmOut,
+ int crowAccepting = RunTransitionTable(ppass, psstrmIn, psstrmOut,
prgrowAccepting, prgcslotMatched);
// Nothing matched; fail quickly.
@@ -274,9 +274,11 @@ int GrFSM::GetRuleToApply(GrTableManager * ptman, GrPass * ppass,
@param prgrowAccepting - array to fill in with accepting rows
@param prgcslotMatched - corresponding array with number of slots matched
----------------------------------------------------------------------------------------------*/
-int GrFSM::RunTransitionTable(GrSlotStream * psstrmIn, GrSlotStream * psstrmOut,
+int GrFSM::RunTransitionTable(GrPass * ppass, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut,
int * prgrowAccepting, int * prgcslotMatched)
{
+ int ipass = ppass->PassNumber();
+
// Remember we're reading the pre-context items from the output stream, not the input.
int cslotPreContextAvail = psstrmOut->WritePos();
@@ -305,12 +307,24 @@ int GrFSM::RunTransitionTable(GrSlotStream * psstrmIn, GrSlotStream * psstrmOut,
// no more input
return (prowTop - prgrowAccepting);
- // Get next glyph.
- gid16 chwGlyphID = (cslot < 0) ?
- psstrmOut->PeekBack(cslot)->GlyphID() :
- psstrmIn->Peek(cslot)->GlyphID();
-
- int col = FindColumn(chwGlyphID);
+ // Figure out what column the input glyph belong in.
+ // Since this is a time-critical routine, we cache the results for the current pass.
+ GrSlotState * pslot = (cslot < 0) ?
+ psstrmOut->PeekBack(cslot) :
+ psstrmIn->Peek(cslot);
+ int col;
+ if (pslot->PassNumberForColumn() == ipass)
+ {
+ col = pslot->FsmColumn();
+ }
+ else
+ {
+ gid16 chwGlyphID = (cslot < 0) ?
+ psstrmOut->PeekBack(cslot)->GlyphID() :
+ psstrmIn->Peek(cslot)->GlyphID();
+ col = FindColumn(chwGlyphID);
+ pslot->CacheFsmColumn(ipass, col);
+ }
int rowNext;
if (col < 0)
rowNext = 0;
@@ -488,8 +502,10 @@ int GrFSM::FindColumn(gid16 chwGlyphID)
else
{
nTest = pmcrCurr->m_chwFirst - chwGlyphID;
- if (nTest < 0)
- nTest = (chwGlyphID <= pmcrCurr->m_chwLast) ? 0 : nTest;
+ if (nTest < 0 && chwGlyphID <= pmcrCurr->m_chwLast)
+ //nTest = 0;
+ // This is a tiny bit more efficient:
+ return pmcrCurr->m_col;
}
if (nTest == 0)
diff --git a/Build/source/libs/graphite-engine/src/segment/GrFSM.h b/Build/source/libs/graphite-engine/src/segment/GrFSM.h
index 483d7bc2be8..b1909553daa 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrFSM.h
+++ b/Build/source/libs/graphite-engine/src/segment/GrFSM.h
@@ -107,7 +107,9 @@ protected:
Do these seem to be worth the inconvenience of added complexity in understanding
and debugging?
----------------------------------------------------------------------------------------------*/
-class GrFSM {
+class GrFSM
+{
+ friend class FontMemoryUsage;
public:
GrFSM() :
@@ -140,7 +142,7 @@ public:
int GetRuleToApply(GrTableManager *, GrPass * ppass,
GrSlotStream * psstrmIn, GrSlotStream * psstrmOut);
- int RunTransitionTable(GrSlotStream * psstrmIn, GrSlotStream * psstrmOut,
+ int RunTransitionTable(GrPass * ppass, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut,
int * prgrowAccepting, int * prgcslotMatched);
int RunTransitionTableOptimized(GrSlotStream * psstrmIn, GrSlotStream * psstrmOut,
int * prgrowAccepting, int * prgcslotMatched);
@@ -182,6 +184,7 @@ protected:
data16 * m_prgrulnMatched; // long ordered list of rule indices matched by
// subsequent states; total length is sum of number
// of rules matched for each accepting state
+ int m_crulnMatched; // needed only for memory instrumentation
// Transition matrix--for optimized version:
// short ** m_prgprgrowXitions; // ((m_crow-m_crowFinal) * m_ccol) of these;
diff --git a/Build/source/libs/graphite-engine/src/segment/GrFeature.cpp b/Build/source/libs/graphite-engine/src/segment/GrFeature.cpp
index 3e488462a74..7863220b80a 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrFeature.cpp
+++ b/Build/source/libs/graphite-engine/src/segment/GrFeature.cpp
@@ -210,6 +210,7 @@ bool GrLangTable::ReadFromFont(GrIStream * pgrstrm, int fxdVersion)
Assert(cb % sizeof(FeatSet) == 0); // # of bytes fits nicely into FeatSet class
int cfset = cb / sizeof(FeatSet);
m_prgfset = new FeatSet[cfset];
+ m_cfset = cfset;
grstrm.ReadBlockFromFont(m_prgfset, cb);
return true;
diff --git a/Build/source/libs/graphite-engine/src/segment/GrGlyphTable.h b/Build/source/libs/graphite-engine/src/segment/GrGlyphTable.h
index b2a558ebfbd..bec0e518dee 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrGlyphTable.h
+++ b/Build/source/libs/graphite-engine/src/segment/GrGlyphTable.h
@@ -93,7 +93,7 @@ protected:
/*----------------------------------------------------------------------------------------------
Contains runs of attribute values for all the glyphs in the font; corresponds to
- the "Glat" table in the ECF file.
+ the "Glat" table in the font.
Hungarian: gatbl
----------------------------------------------------------------------------------------------*/
@@ -102,6 +102,7 @@ class GrGlyphAttrTable
{
friend class GrGlyphTable;
friend class GrGlyphSubTable;
+ friend class FontMemoryUsage;
protected:
// Constructor:
@@ -129,17 +130,17 @@ protected:
int GlyphAttr16BitValue(int ibMin, int ibLim, byte bAttrID);
protected:
- int m_fxdSilfVersion; // version number of the Silf table, which is used
- // to interpret the attribute values
+ int m_fxdSilfVersion; // version number of the Silf table, which is used
+ // to interpret the attribute values
// Block of variable-length glyph attribute runs, matching the format of
// GrGlyphAttrRun. We don't store instances of that class here because they
// are variable length, and it would be too slow to read them individually from the
- // ECF file. Instead, we set up a single instance in the method that accesses the values;
+ // font. Instead, we set up a single instance in the method that accesses the values;
// having this instance will help debugging. Eventually we may want to do without it,
// if it would help efficiency.
- int m_cbEntryBufLen; // do we really need this?
- byte * m_prgbBIGEntries;
+ int m_cbEntryBufLen; // needed only for memory instrumentation
+ byte * m_prgbBIGEntries;
//:Ignore
#ifdef OLD_TEST_STUFF
@@ -155,19 +156,20 @@ public:
};
/*----------------------------------------------------------------------------------------------
- One glyph table per font (style) file; corresponds to the "Gloc" table in the ECF.
+ One glyph table per font (style) file; corresponds to the "Gloc" table in the font.
Currently there is only considered to be one style per file, so there is only one of
these. It holds the (non-zero) glyph attribute values for every glyph in the font.
Hungarian: gstbl
- Review: Eventually we may need to make a subclass that uses 32-values for the offsets,
+ Review: Eventually we may need to make a subclass that uses 32-bit values for the offsets,
or just use a separate array pointer in this class. Which would be preferable?
----------------------------------------------------------------------------------------------*/
class GrGlyphSubTable
{
friend class GrGlyphTable;
+ friend class FontMemoryUsage;
public:
// Constructor:
@@ -246,27 +248,27 @@ public:
}
protected:
- int m_fxdSilfVersion; // version number of the Silf table, which is used
- // to interpret the attribute values
- bool m_fHasDebugStrings; // are debugging strings loaded into memory?
+ int m_fxdSilfVersion; // version number of the Silf table, which is used
+ // to interpret the attribute values
+ bool m_fHasDebugStrings; // are debugging strings loaded into memory?
- int m_nAttrIDLim; // number of glyph attributes
- int m_cComponents; // number of initial glyph attributes that
- // represent ligature components
- int m_cnCompPerLig;
+ int m_nAttrIDLim; // number of glyph attributes
+ int m_cComponents; // number of initial glyph attributes that
+ // represent ligature components
+ int m_cnCompPerLig;
- GrGlyphAttrTable * m_pgatbl;
- byte * m_prgibBIGAttrValues; // byte offsets for glyph attr values
- bool m_fGlocShort; // flag for Gloc table format
- data16 * m_prgibBIGGlyphAttrDebug; // byte offsets for glyph attr debug strings
+ GrGlyphAttrTable * m_pgatbl;
+ byte * m_prgibBIGAttrValues; // byte offsets for glyph attr values - BIG endian
+ bool m_fGlocShort; // flag for Gloc table format
+ data16 * m_prgibBIGGlyphAttrDebug; // byte offsets for glyph attr debug strings - BIG endian
- data16 m_chwBWAttr; // breakweight attr ID; needed for converting
- // between versions
+ data16 m_chwBWAttr; // breakweight attr ID; needed for converting
+ // between versions
// Attr IDs for justify.0.stretch and justify.0.stretchHW; these must always be looked
// up in tandem.
- data16 m_chwJStrAttr;
- data16 m_chwJStrHWAttr;
+ data16 m_chwJStrAttr;
+ data16 m_chwJStrHWAttr;
int * m_prgnDefinedComponents; // for each glyph, cache list of component attributes that
// are defined
@@ -292,6 +294,7 @@ public:
class GrGlyphTable
{
friend class GrGlyphSubTable;
+ friend class FontMemoryUsage;
public:
// Constructor:
diff --git a/Build/source/libs/graphite-engine/src/segment/GrPass.cpp b/Build/source/libs/graphite-engine/src/segment/GrPass.cpp
index 96e88ac150e..8e2048f0f6f 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrPass.cpp
+++ b/Build/source/libs/graphite-engine/src/segment/GrPass.cpp
@@ -44,11 +44,12 @@ namespace gr
----------------------------------------------------------------------------------------------*/
GrPass::GrPass(int i)
: m_ipass(i),
- vnStack(128),
+ m_fxdVersion(0),
m_nMaxRuleContext(0),
m_pfsm(NULL),
m_nMaxRuleLoop(0),
m_nMaxBackup(0),
+ m_crul(0),
m_prgchwRuleSortKeys(NULL),
m_prgcritRulePreModContext(NULL),
m_cbPassConstraint(0),
@@ -57,10 +58,14 @@ GrPass::GrPass(int i)
m_prgbPConstraintBlock(NULL),
m_prgbConstraintBlock(NULL),
m_prgbActionBlock(NULL),
+ m_cbConstraints(0),
+ m_cbActions(0),
m_prgibConstraintDebug(NULL),
m_prgibRuleDebug(NULL),
m_fCheckRules(false),
- m_prgfRuleOkay(NULL)
+ m_prgfRuleOkay(NULL),
+ m_vnStack(128),
+ m_pzpst(NULL)
{
}
@@ -227,14 +232,17 @@ bool GrPass::ReadFromFont(GrIStream & grstrm, int fxdSilfVersion, int fxdRuleVer
int cb = m_cbPassConstraint;
m_prgbPConstraintBlock = new byte[cb];
grstrm.ReadBlockFromFont(m_prgbPConstraintBlock, cb);
+ m_cbConstraints = cb;
cb = m_prgibConstraintStart[m_crul];
m_prgbConstraintBlock = new byte[cb];
grstrm.ReadBlockFromFont(m_prgbConstraintBlock, cb);
+ m_cbConstraints += cb;
cb = m_prgibActionStart[m_crul];
m_prgbActionBlock = new byte[cb];
grstrm.ReadBlockFromFont(m_prgbActionBlock, cb);
+ m_cbActions = cb;
// Rule-validity flags
m_prgfRuleOkay = new bool[m_crul];
@@ -773,7 +781,8 @@ int GrPass::ExtendFinalOutput(GrTableManager * ptman,
// Assert(m_cslotSkipToResync == 0);
int islotOutputLB = -1;
- int islotInitWritePos = psstrmOutput->WritePos();
+ //int islotInitWritePos = psstrmOutput->WritePos();
+ int islotNoLbUpTo = psstrmOutput->WritePos();;
while (true)
{
@@ -859,9 +868,12 @@ int GrPass::ExtendFinalOutput(GrTableManager * ptman,
RunRule(ptman, ruln, psstrmInput, psstrmOutput);
if (fHaveLineBreak)
+ {
islotOutputLB =
psstrmOutput->FindFinalLineBreak(ptman->LBGlyphID(),
- islotInitWritePos, psstrmOutput->WritePos());
+ islotNoLbUpTo, psstrmOutput->WritePos());
+ islotNoLbUpTo = psstrmOutput->WritePos();
+ }
psstrmOutput->CalcIndexOffset(ptman);
}
@@ -1715,7 +1727,7 @@ int GrPass::Unwind(GrTableManager * ptman,
if (!psstrmIn->NoReproc())
islotIn = min(islotIn, psstrmIn->ReprocMin());
psstrmIn->ClearReprocBuffer();
- int islotOut;
+ int islotOut = 0;
if (islotIn < psstrmIn->SlotsSkippedToResync() ||
islotIn == 0 ||
psstrmIn->ReadPos() == 0)
diff --git a/Build/source/libs/graphite-engine/src/segment/GrPass.h b/Build/source/libs/graphite-engine/src/segment/GrPass.h
index 9afaf8ac518..aad6b3425b8 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrPass.h
+++ b/Build/source/libs/graphite-engine/src/segment/GrPass.h
@@ -35,6 +35,7 @@ class PassState {
friend class GrSubPass;
friend class GrBidiPass;
friend class GrPosPass;
+ friend class FontMemoryUsage;
public:
PassState()
@@ -135,6 +136,7 @@ protected:
Hungarian: pass
----------------------------------------------------------------------------------------------*/
class GrPass {
+ friend class FontMemoryUsage;
protected:
// Action command codes; these MUST match the corresponding definitions in the compiler:
@@ -190,6 +192,8 @@ public:
// Destructor:
virtual ~GrPass();
+ int PassNumber() { return m_ipass; }
+
bool ReadFromFont(GrIStream & grstrm, int fxdSilfVersion, int fxdRuleVersion, int nOffset);
void InitializeWithNoRules();
@@ -392,7 +396,6 @@ protected:
int m_fxdVersion;
- std::vector<int> vnStack;
// number of items required from previous pass; don't access directly, use the getter
// method, because GrBidiPass overrides to always use 1.
int m_nMaxRuleContext;
@@ -425,6 +428,9 @@ protected:
byte * m_prgbConstraintBlock; // rule constraints
byte * m_prgbActionBlock;
+ int m_cbConstraints; // needed for memory instrumentation only
+ int m_cbActions; // needed for memory instrumentation only
+
bool m_fHasDebugStrings;
data16 * m_prgibConstraintDebug; // m_crul+1 of these
data16 * m_prgibRuleDebug; // m_crul+1 of these
@@ -432,6 +438,9 @@ protected:
bool m_fCheckRules;
bool * m_prgfRuleOkay;
+ std::vector<int> m_vnStack; // for stack machine processing (more efficient than creating the
+ // vector each time)
+
// state of process for this pass
PassState * m_pzpst;
@@ -470,7 +479,10 @@ public:
Hungarian: pass
----------------------------------------------------------------------------------------------*/
-class GrGlyphGenPass : public GrPass {
+class GrGlyphGenPass : public GrPass
+{
+ friend class FontMemoryUsage;
+
public:
GrGlyphGenPass(int ipass) : GrPass(ipass)
{
@@ -497,7 +509,10 @@ protected:
Hungarian: pass
----------------------------------------------------------------------------------------------*/
-class GrLineBreakPass : public GrPass {
+class GrLineBreakPass : public GrPass
+{
+ friend class FontMemoryUsage;
+
public:
GrLineBreakPass(int ipass) : GrPass(ipass)
{
@@ -538,7 +553,10 @@ public:
Hungarian: pass
----------------------------------------------------------------------------------------------*/
-class GrSubPass : public GrPass {
+class GrSubPass : public GrPass
+{
+ friend class FontMemoryUsage;
+
public:
GrSubPass(int ipass) : GrPass(ipass)
{
@@ -615,6 +633,8 @@ public:
----------------------------------------------------------------------------------------------*/
class GrBidiPass : public GrSubPass
{
+ friend class FontMemoryUsage;
+
public:
// Constructor:
GrBidiPass(int ipass)
@@ -677,7 +697,10 @@ public:
Hungarian: pass
----------------------------------------------------------------------------------------------*/
-class GrPosPass : public GrPass {
+class GrPosPass : public GrPass
+{
+ friend class FontMemoryUsage;
+
public:
GrPosPass(int ipass) : GrPass(ipass)
{
diff --git a/Build/source/libs/graphite-engine/src/segment/GrPassActionCode.cpp b/Build/source/libs/graphite-engine/src/segment/GrPassActionCode.cpp
index 7c85aabf398..83c58b27e48 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrPassActionCode.cpp
+++ b/Build/source/libs/graphite-engine/src/segment/GrPassActionCode.cpp
@@ -10,6 +10,8 @@ Last reviewed: Not yet.
Description:
A continution of the GrPass file, including functions to run the action commands.
+
+This comment could create a merge conflict. It can be removed.
----------------------------------------------------------------------------------------------*/
//:>********************************************************************************************
@@ -64,8 +66,9 @@ int GrPass::RunCommandCode(GrTableManager * ptman,
{
byte * pbNext = pbStart;
- std::vector<int> vnStack;
+// std::vector<int> vnStack;
// vnStack.EnsureSpace(128); // make it nice and big
+ m_vnStack.clear();
gAssert(fConstraints || islot == 0);
@@ -85,7 +88,7 @@ int GrPass::RunCommandCode(GrTableManager * ptman,
nRet = RunOneCommand(ptman, fConstraints, op,
&pbNext, &fMustGet, &fInserting,
psstrmIn, psstrmOut, islot,
- vnStack, &smf);
+ m_vnStack, &smf);
if (smf == ksmfDone)
return nRet;
diff --git a/Build/source/libs/graphite-engine/src/segment/GrSlotState.cpp b/Build/source/libs/graphite-engine/src/segment/GrSlotState.cpp
index 892318912e1..b18ae95a63f 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrSlotState.cpp
+++ b/Build/source/libs/graphite-engine/src/segment/GrSlotState.cpp
@@ -58,6 +58,8 @@ void GrSlotState::Initialize(gid16 chw, GrEngine * pgreng,
u_intslot * pFeatBuf = PFeatureBuf();
for (size_t i = 0; i < m_cnFeat; i++)
pFeatBuf[i].nValue = fval.m_rgnFValues[i];
+ m_ipassFsmCol = -1;
+ m_colFsm = -1;
m_ipassModified = ipass;
m_ichwSegOffset = ichwSegOffset;
@@ -100,6 +102,8 @@ void GrSlotState::Initialize(gid16 chw, GrEngine * pgreng,
m_vpslotAssoc.clear();
pgreng->InitSlot(this);
// Caller is responsible for setting m_spsl.
+ m_ipassFsmCol = -1;
+ m_colFsm = -1;
}
// for inserting new slots after pass 0 (under-pos and unicode are irrelevant)
@@ -121,6 +125,8 @@ void GrSlotState::Initialize(gid16 chw, GrEngine * pgreng,
m_vpslotAssoc.clear();
pgreng->InitSlot(this);
m_spsl = kspslNone;
+ m_ipassFsmCol = -1;
+ m_colFsm = -1;
}
/*----------------------------------------------------------------------------------------------
@@ -129,18 +135,17 @@ void GrSlotState::Initialize(gid16 chw, GrEngine * pgreng,
----------------------------------------------------------------------------------------------*/
void GrSlotState::InitializeFrom(GrSlotState * pslotOld, int ipass)
{
+ CopyFrom(pslotOld, false);
+
m_ipassModified = ipass;
m_pslotPrevState = pslotOld;
m_ichwSegOffset = kInvalid;
m_vpslotAssoc.clear();
m_vpslotAssoc.push_back(pslotOld);
- m_dislotRootFixed = pslotOld->m_dislotRootFixed;
- m_vdislotAttLeaves.resize(pslotOld->m_vdislotAttLeaves.size());
- for (size_t i = 0; i < pslotOld->m_vdislotAttLeaves.size(); i++)
- m_vdislotAttLeaves[i] = pslotOld->m_vdislotAttLeaves[i];
-
- GrSlotAbstract::CopyFrom(pslotOld);
+ // Since we're going on to a new pass, no point in copying these:
+ m_ipassFsmCol = -1;
+ m_colFsm = -1;
////FixAttachmentTree(pslotOld);
}
@@ -157,17 +162,85 @@ void GrSlotState::CopyFeaturesFrom(GrSlotState * pslotSrc)
/*----------------------------------------------------------------------------------------------
Copy the basic information.
- Warning: this function will break if GrSlotState and subclasses are given virtual
+ Warning: the functions below will break if GrSlotState and subclasses are given virtual
methods. In that case, we will need to copy from the address of the first variable in
GrSlotAbstract.
----------------------------------------------------------------------------------------------*/
-void GrSlotAbstract::CopyFrom(GrSlotState * pslot)
+void GrSlotState::CopyFrom(GrSlotState * pslot, bool fCopyEverything)
+{
+ GrSlotAbstract::CopyAbstractFrom(pslot);
+ std::copy(pslot->m_prgnVarLenBuf, pslot->m_prgnVarLenBuf + CExtraSpace(), m_prgnVarLenBuf);
+
+ if (fCopyEverything)
+ {
+ Assert(false);
+ m_ipassModified = pslot->m_ipassModified;
+ m_pslotPrevState = pslot->m_pslotPrevState;
+ m_ichwSegOffset = pslot->m_ichwSegOffset;
+ m_colFsm = pslot->m_colFsm;
+ m_ipassFsmCol = pslot->m_ipassFsmCol;
+ // TODO: copy m_vpslotAssocs.
+ m_fNeutralAssocs = pslot->m_fNeutralAssocs;
+ }
+
+ m_dislotRootFixed = pslot->m_dislotRootFixed;
+
+ m_vdislotAttLeaves.resize(pslot->m_vdislotAttLeaves.size());
+ for (size_t i = 0; i < pslot->m_vdislotAttLeaves.size(); i++)
+ m_vdislotAttLeaves[i] = pslot->m_vdislotAttLeaves[i];
+
+ m_islotPosPass = pslot->m_islotPosPass;
+ m_nUnicode = pslot->m_nUnicode;
+ m_dircProc = pslot->m_dircProc;
+ m_fDirProcessed = pslot->m_fDirProcessed;
+ m_cnUserDefn = pslot->m_cnUserDefn;
+ m_cnFeat = pslot->m_cnFeat;
+ m_bStyleIndex = pslot->m_bStyleIndex;
+ m_mAdvanceX = pslot->m_mAdvanceX;
+ m_mAdvanceY = pslot->m_mAdvanceY;
+ m_mShiftX = pslot->m_mShiftX;
+ m_mShiftY = pslot->m_mShiftY;
+ m_srAttachTo = pslot->m_srAttachTo;
+ m_nAttachLevel = pslot->m_nAttachLevel;
+ m_mAttachAtX = pslot->m_mAttachAtX;
+ m_mAttachAtY = pslot->m_mAttachAtY;
+ m_mAttachAtXOffset = pslot->m_mAttachAtXOffset;
+ m_mAttachAtYOffset = pslot->m_mAttachAtYOffset;
+ m_mAttachWithX = pslot->m_mAttachWithX;
+ m_mAttachWithY = pslot->m_mAttachWithY;
+ m_mAttachWithXOffset = pslot->m_mAttachWithXOffset;
+ m_mAttachWithYOffset = pslot->m_mAttachWithYOffset;
+ m_nAttachAtGpoint = pslot->m_nAttachAtGpoint;
+ m_nAttachWithGpoint = pslot->m_nAttachWithGpoint;
+ m_fAttachMod = pslot->m_fAttachMod;
+ m_fShiftMod = pslot->m_fShiftMod;
+ m_fIgnoreAdvance = pslot->m_fIgnoreAdvance;
+
+ m_nCompositeLevel = kNegInfinity; // uncalculated, so don't need to copy the positions??
+}
+
+void GrSlotAbstract::CopyAbstractFrom(GrSlotState * pslot)
{
u_intslot * pnBufSave = m_prgnVarLenBuf;
*this = *pslot;
m_prgnVarLenBuf = pnBufSave;
Assert(m_prgnVarLenBuf);
- std::copy(pslot->m_prgnVarLenBuf, pslot->m_prgnVarLenBuf + CExtraSpace(), m_prgnVarLenBuf);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Initialize the output slot from the one use within the passes, with the basic information.
+ Warning: this function will break if GrSlotState and subclasses are given virtual
+ methods. In that case, we will need to copy from the address of the first variable in
+ GrSlotAbstract.
+----------------------------------------------------------------------------------------------*/
+void GrSlotOutput::InitializeOutputFrom(GrSlotState * pslot)
+{
+ CopyAbstractFrom(pslot);
+
+ // Copy just the component information, which is of length (m_cnCompPerLig * 2)
+ //std::copy(pslot->PCompRefBuf(),
+ // pslot->PCompRefBuf() + (m_cnCompPerLig * 2),
+ // this->PCompRefBufSlout());
}
/*----------------------------------------------------------------------------------------------
@@ -232,7 +305,7 @@ void GrSlotState::EnsureCacheForOutput(GrTableManager * ptman)
m_xysGlyphWidth = 0;
m_xysAdvX = 0;
m_xysAdvY = 0;
- m_fIsSpace = true;
+ m_bIsSpace = true;
}
else
{
@@ -478,7 +551,7 @@ void GrSlotState::AllComponentRefs(std::vector<int> & vichw)
Get the value of the component.???.ref attribute for the slot.
Note that 'i' is the local index for the component as defined for this glyph.
----------------------------------------------------------------------------------------------*/
-GrSlotState * GrSlotAbstract::CompRefSlot(int i)
+GrSlotState * GrSlotState::CompRefSlot(int i)
{
Assert(i < m_cnCompPerLig);
if (i < m_cnCompPerLig)
@@ -624,45 +697,42 @@ float GrSlotOutput::GlyphMetricLogUnits(Font * pfont, int nMetricID)
return GetGlyphMetric(pfont, nMetricID, m_chwActual);
}
-float GrSlotOutput::GlyphMetricLogUnits(int gmet)
-{
- // When the font is not passed as an argument, the values better be cached!
-
- switch (gmet)
- { // There may be off by one errors below, depending on what width and height mean
- case kgmetLsb:
- return m_xysGlyphX;
- case kgmetRsb:
- return (m_xysAdvX - m_xysGlyphX - m_xysGlyphWidth);
- case kgmetBbTop:
- return m_xysGlyphY;
- case kgmetBbBottom:
- return (m_xysGlyphY - m_xysGlyphHeight);
- case kgmetBbLeft:
- return m_xysGlyphX;
- case kgmetBbRight:
- return (m_xysGlyphX + m_xysGlyphWidth);
- case kgmetBbHeight:
- return m_xysGlyphHeight;
- case kgmetBbWidth:
- return m_xysGlyphWidth;
- case kgmetAdvWidth:
- return m_xysAdvX;
- case kgmetAdvHeight:
- return m_xysAdvY;
- default:
- Warn("GetGlyphMetric was asked for an illegal metric.");
- };
-
- return 0;
-}
+//float GrSlotOutput::GlyphMetricLogUnits(int gmet) -- obsolete: no longer caching these values
+//{
+// // When the font is not passed as an argument, the values better be cached!
+//
+// switch (gmet)
+// { // There may be off by one errors below, depending on what width and height mean
+// case kgmetLsb:
+// return m_xysGlyphX;
+// case kgmetRsb:
+// return (m_xysAdvX - m_xysGlyphX - m_xysGlyphWidth);
+// case kgmetBbTop:
+// return m_xysGlyphY;
+// case kgmetBbBottom:
+// return (m_xysGlyphY - m_xysGlyphHeight);
+// case kgmetBbLeft:
+// return m_xysGlyphX;
+// case kgmetBbRight:
+// return (m_xysGlyphX + m_xysGlyphWidth);
+// case kgmetBbHeight:
+// return m_xysGlyphHeight;
+// case kgmetBbWidth:
+// return m_xysGlyphWidth;
+// case kgmetAdvWidth:
+// return m_xysAdvX;
+// case kgmetAdvHeight:
+// return m_xysAdvY;
+// default:
+// Warn("GetGlyphMetric was asked for an illegal metric.");
+// };
+//
+// return 0;
+//}
float GrSlotAbstract::GetGlyphMetric(Font * pfont, int nMetricID, gid16 chwGlyphID)
{
- //GrResult res;
- float xysRet = 0;
-
GlyphMetric gmet = GlyphMetric(nMetricID);
float yAscent, yDescent;
@@ -671,91 +741,70 @@ float GrSlotAbstract::GetGlyphMetric(Font * pfont, int nMetricID, gid16 chwGlyph
if (kgmetAscent == gmet)
{
- if (m_xysFontAscent != -1)
- return m_xysFontAscent;
- //GrResult res = pgg->get_FontAscent(&xysRet);
- //if (ResultFailed(res))
- //{
- // WARN(res);
- // return 0;
- //}
+ //if (m_xysFontAscent != -1)
+ // return m_xysFontAscent;
pfont->getFontMetrics(&yAscent);
- m_xysFontAscent = xysRet;
- if (pfont)
- m_xysFontAscent = yAscent;
- return xysRet;
+ //m_xysFontAscent = xysRet;
+ //if (pfont)
+ // m_xysFontAscent = yAscent;
+ return yAscent;
}
if (kgmetDescent == gmet)
{
- if (m_xysFontDescent != -1)
- return m_xysFontDescent;
- //GrResult res = pgg->get_FontDescent(&xysRet);
- //if (ResultFailed(res))
- //{
- // WARN(res);
- // return 0;
- // m_xysFontDescent = xysRet;
- //}
+ //if (m_xysFontDescent != -1)
+ // return m_xysFontDescent;
pfont->getFontMetrics(NULL, &yDescent);
- m_xysFontDescent = xysRet;
- if (pfont)
- m_xysFontDescent = yDescent;
- return xysRet;
+ //m_xysFontDescent = xysRet;
+ //if (pfont)
+ // m_xysFontDescent = yDescent;
+ return yDescent;
}
- if (m_xysGlyphWidth == -1)
- {
- //res = pgg->GetGlyphMetrics(chwGlyphID, &m_xysGlyphWidth, &m_xysGlyphHeight,
- // &m_xysGlyphX, &m_xysGlyphY, &m_xysAdvX, &m_xysAdvY);
- //if (ResultFailed(res))
- //{
- // //WARN(res);
- // //return 0;
- // ThrowHr(WarnHr(res));
- //}
-
+ float xysGlyphX, xysGlyphY, xysGlyphWidth, xysGlyphHeight, xysAdvX, xysAdvY;
+ //if (m_xysGlyphWidth == -1)
+ //{
pfont->getGlyphMetrics(chwGlyphID, rectBb, ptAdvances);
- m_xysGlyphX = rectBb.left;
- m_xysGlyphY = rectBb.top;
- m_xysGlyphWidth = (rectBb.right - rectBb.left);
- m_xysGlyphHeight = (rectBb.top - rectBb.bottom);
- m_xysAdvX = ptAdvances.x;
- m_xysAdvY = ptAdvances.y;
+ xysGlyphX = rectBb.left;
+ xysGlyphY = rectBb.top;
+ xysGlyphWidth = (rectBb.right - rectBb.left);
+ xysGlyphHeight = (rectBb.top - rectBb.bottom);
+ xysAdvX = ptAdvances.x;
+ xysAdvY = ptAdvances.y;
- m_fIsSpace = (0 == m_xysGlyphX && 0 == m_xysGlyphY); // should agree with test done in IsSpace() below
+ m_bIsSpace = (0 == xysGlyphX && 0 == xysGlyphY); // should agree with test done in IsSpace() below
- if (m_fIsSpace)
+ if (m_bIsSpace == 1)
{
// White space glyph - only case where nGlyphX == nGlyphY == 0
// nGlyphWidth & nGlyphHeight are always set to 16 for unknown reasons, so correct.
- m_xysGlyphWidth = m_xysGlyphHeight = 0;
+ xysGlyphWidth = xysGlyphHeight = 0;
}
- }
+ //}
switch (gmet)
- { // There may be off by one errors below, depending on what width and height mean
+ { // There may be off-by-one errors below, depending on what width and height mean
case kgmetLsb:
- return m_xysGlyphX;
+ return xysGlyphX;
case kgmetRsb:
- return (m_xysAdvX - m_xysGlyphX - m_xysGlyphWidth);
+ return (xysAdvX - xysGlyphX - xysGlyphWidth);
case kgmetBbTop:
- return m_xysGlyphY;
+ return xysGlyphY;
case kgmetBbBottom:
- return (m_xysGlyphY - m_xysGlyphHeight);
+ return (xysGlyphY - xysGlyphHeight);
case kgmetBbLeft:
- return m_xysGlyphX;
+ return xysGlyphX;
case kgmetBbRight:
- return (m_xysGlyphX + m_xysGlyphWidth);
+ return (xysGlyphX + xysGlyphWidth);
case kgmetBbHeight:
- return m_xysGlyphHeight;
+ return xysGlyphHeight;
case kgmetBbWidth:
- return m_xysGlyphWidth;
+ return xysGlyphWidth;
case kgmetAdvWidth:
- return m_xysAdvX;
+ return xysAdvX;
case kgmetAdvHeight:
- return m_xysAdvY;
+ return xysAdvY;
default:
Warn("GetGlyphMetric was asked for an illegal metric.");
};
@@ -786,19 +835,23 @@ int GrSlotState::IsSpace(GrTableManager * ptman)
//// ptman->State()->Font()->getGlyphMetrics(gidActual, rectBb, ptAdvances);
////}
- GetGlyphMetric(ptman->State()->GetFont(), kgmetBbLeft, gidActual);
+ if (m_bIsSpace == -1)
+ GetGlyphMetric(ptman->State()->GetFont(), kgmetBbLeft, gidActual);
// One call is enough to cache the information.
//GetGlyphMetric(ptman->State()->Font(), kgmetBbBottom, gidActual);
// should agree with test done in GetGlyphMetric() above
- //////m_fIsSpace = (0 == m_xysGlyphX && 0 == m_xysGlyphY);
+ //////m_bIsSpace = (0 == m_xysGlyphX && 0 == m_xysGlyphY);
- return m_fIsSpace;
+ Assert(m_bIsSpace == 0 || m_bIsSpace == 1);
+
+ return m_bIsSpace;
}
bool GrSlotOutput::IsSpace()
{
- return m_fIsSpace;
+ Assert(m_bIsSpace == 0 || m_bIsSpace == 1);
+ return m_bIsSpace;
}
/*----------------------------------------------------------------------------------------------
@@ -1059,9 +1112,9 @@ void GrSlotState::InitLeafMetrics(GrTableManager * ptman, GrSlotState * pslotRoo
if (IsBase())
{
- // These two are actually meaningless numbers, for the base, but set them
- // to something reasonable.
- m_xsOffsetX = xsShiftX;
+ // The x-value below has to be zero because the shift is incorporated into
+ // m_xsRootShiftX. (m_ysRootShiftY, on the other hand, isn't used anywhere.)
+ m_xsOffsetX = 0;
m_ysOffsetY = ysShiftY;
m_xsRootShiftX = xsShiftX;
@@ -1383,16 +1436,14 @@ void GrSlotOutput::ExactCopyFrom(GrSlotOutput * pslout, u_intslot * pnVarLenBuf,
m_ichwAfterAssoc = pslout->m_ichwAfterAssoc;
m_cComponents = pslout->m_cComponents;
- for (size_t iislout = 0; iislout < pslout->m_visloutClusterMembers.size(); iislout++)
- m_visloutClusterMembers.push_back(pslout->m_visloutClusterMembers[iislout]);
-
m_isloutClusterBase = pslout->m_isloutClusterBase;
+ m_disloutCluster = pslout->m_disloutCluster;
m_xsClusterXOffset = pslout->m_xsClusterXOffset;
m_xsClusterAdvance = pslout->m_xsClusterAdvance;
m_igbb = pslout->m_igbb;
m_xsAdvanceX = pslout->m_xsAdvanceX;
- m_ysAdvanceY = pslout->m_ysAdvanceY;
- m_rectBB = pslout->m_rectBB;
+// m_ysAdvanceY = pslout->m_ysAdvanceY;
+// m_rectBB = pslout->m_rectBB;
}
/*----------------------------------------------------------------------------------------------
@@ -1404,8 +1455,24 @@ void GrSlotOutput::ShiftForDirDepthChange(float dxsSegWidth)
float dxsShift = dxsSegWidth - m_xsAdvanceX - (2 * m_xsPositionX);
int tmp; tmp = (int) dxsShift;
m_xsPositionX += dxsShift;
- m_rectBB.left += dxsShift;
- m_rectBB.right += dxsShift;
+// m_rectBB.left += dxsShift;
+// m_rectBB.right += dxsShift;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return the indices of all the glyphs attached to this cluster, in logical order.
+ Return an empty vector if this glyph is not the base glyph or if there are no
+ attached glyphs.
+ This method return glyph indices, not slot indices.
+----------------------------------------------------------------------------------------------*/
+void GrSlotOutput::ClusterMembers(Segment * pseg, int isloutThis, std::vector<int> & visloutRet)
+{
+ if (m_isloutClusterBase == -1 || m_isloutClusterBase == isloutThis) // yes, a base
+ pseg->ClusterMembersForGlyph(isloutThis, m_disloutCluster, visloutRet);
+ else
+ {
+ Assert(visloutRet.size() == 0);
+ }
}
} // namespace gr
diff --git a/Build/source/libs/graphite-engine/src/segment/GrSlotState.h b/Build/source/libs/graphite-engine/src/segment/GrSlotState.h
index f9110d7b68c..400f21d5800 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrSlotState.h
+++ b/Build/source/libs/graphite-engine/src/segment/GrSlotState.h
@@ -11,7 +11,7 @@ Last reviewed: Not yet.
Copyright (C) 1999 by SIL International. All rights reserved.
Description:
- Class GrSlotAbstract, GrSlotState, and GrSlotOutput
+ Classes GrSlotAbstract, GrSlotState, and GrSlotOutput
----------------------------------------------------------------------------------------------*/
#ifdef _MSC_VER
#pragma once
@@ -53,36 +53,14 @@ public:
// the table manager is responsible for destroying the contents of m_prgnVarLenBuf
}
- void BasicInitialize(int cnUserDefn, int cnCompPerLig, int cnFeat, u_intslot * pnBuf)
+ void BasicInitializeAbstract(int cnCompPerLig, u_intslot * pnBuf)
{
- m_dirc = kNotYetSet;
- m_lb = kNotYetSet;
+ m_dirc = kNotYetSet8;
+ m_lb = kNotYetSet8;
m_fInsertBefore = true;
m_nDirLevel = -1;
- m_fHasComponents = false;
-
- m_xysGlyphWidth = -1;
- m_xysFontAscent = -1;
- m_xysFontDescent = -1;
-
- m_mAdvanceX = kNotYetSet;
- m_mAdvanceY = kNotYetSet;
- m_mShiftX = 0;
- m_mShiftY = 0;
- m_srAttachTo = 0;
- m_nAttachLevel = 0;
-
- m_mAttachAtX = kNotYetSet;
- m_mAttachAtY = 0;
- m_nAttachAtGpoint = kNotYetSet;
- m_mAttachAtXOffset = 0;
- m_mAttachAtYOffset = 0;
- m_mAttachWithX = kNotYetSet;
- m_mAttachWithY = 0;
- m_nAttachWithGpoint = kNotYetSet;
- m_mAttachWithXOffset = 0;
- m_mAttachWithYOffset = 0;
+ m_bIsSpace = -1; // unknown
m_fInsertBefore = true;
@@ -95,16 +73,11 @@ public:
m_nJWeight0 = 0;
m_mJWidth0 = 0;
- m_islotPosPass = kNotYetSet;
-
- m_cnUserDefn = byte(cnUserDefn);
m_cnCompPerLig = byte(cnCompPerLig);
- m_cnFeat = byte(cnFeat);
m_prgnVarLenBuf = pnBuf;
-
- m_fAdvXSet = false; // for transduction logging
- m_fAdvYSet = false;
}
+
+ void CopyAbstractFrom(GrSlotState * pslot);
void SetBufferPtr(u_intslot * pn)
{
@@ -115,55 +88,15 @@ public:
gid16 RawActualGlyph() { return m_chwActual; }
float GetGlyphMetric(Font * pfont, int nGlyphMetricID, gid16 chwGlyphID);
- int StyleIndex() { return m_bStyleIndex; }
- void GetFeatureValues(GrFeatureValues * pfval)
- {
- pfval->m_nStyleIndex = m_bStyleIndex;
- std::fill(pfval->m_rgnFValues, pfval->m_rgnFValues + kMaxFeatures, 0);
- for (size_t i = 0; i < m_cnFeat; i++)
- pfval->m_rgnFValues[i] = PFeatureBuf()[i].nValue;
- }
-
- int RawAdvanceX() { return m_mAdvanceX; }
- int RawAdvanceY() { return m_mAdvanceY; }
- int ShiftX() { return m_mShiftX; }
- int ShiftY() { return m_mShiftY; }
-
- int AttachTo() { return m_srAttachTo; }
- int AttachLevel() { return m_nAttachLevel; }
-
- int RawAttachAtX() { return m_mAttachAtX; }
- int AttachAtY() { return m_mAttachAtY; }
- int AttachAtGpoint() { return m_nAttachAtGpoint; }
- int AttachAtXOffset() { return m_mAttachAtXOffset; }
- int AttachAtYOffset() { return m_mAttachAtYOffset; }
-
- int RawAttachWithX() { return m_mAttachWithX; }
- int AttachWithY() { return m_mAttachWithY; }
- int AttachWithGpoint() { return m_nAttachWithGpoint; }
- int AttachWithXOffset() { return m_mAttachWithXOffset; }
- int AttachWithYOffset() { return m_mAttachWithYOffset; }
-
- bool HasComponents() { return m_fHasComponents; }
-
-// int CompRef(int i)
-// {
-// Assert(i < m_cnCompPerLig);
-// if (i < m_cnCompPerLig)
-// return m_rgsrCompRef[i];
-// else
-// return kNotYetSet;
-// }
-
- GrSlotState * CompRefSlot(int i);
+ //GrSlotState * CompRefSlot(int i);
int BreakWeight()
{
- return m_lb;
+ return (int)m_lb;
}
DirCode Directionality()
{
- return DirCode(m_dirc);
+ return DirCode(int(m_dirc));
}
int InsertBefore()
{
@@ -189,104 +122,17 @@ public:
}
void SetSpecialSlotFlag(int spsl)
{
- m_spsl = spsl;
+ m_spsl = sdata8(spsl);
}
- void CopyFrom(GrSlotState * pslot);
-
enum {
kNotYetSet = 0x7FFF,
+ kNotYetSet8 = 0x7F,
kInvalidGlyph = 0xFFFF
};
- int PosPassIndex()
- {
- return m_islotPosPass;
- }
- void SetPosPassIndex(int islot, bool fInputToPosPass1)
- {
- // If we're resetting it, it should be to the same value as before:
- Assert(fInputToPosPass1 || m_islotPosPass == kNotYetSet || m_islotPosPass == islot);
- m_islotPosPass = islot;
- }
- void IncPosPassIndex()
- {
- m_islotPosPass++;
- }
- void ZapPosPassIndex()
- {
- m_islotPosPass = kNotYetSet;
- }
-
gid16 ActualGlyphForOutput(GrTableManager * ptman);
- // Variable-length buffer--includes four sub-buffers:
- // * user-defined variables
- // * component.???.ref assignments
- // * mapping from components used to global attribute IDs for components
- // * feature values
-
- int UserDefn(int slati)
- {
- Assert(slati < m_cnUserDefn);
- return m_prgnVarLenBuf[slati].nValue;
- }
- void SetUserDefn(int slati, int nVal)
- {
- Assert(slati < m_cnUserDefn);
- m_prgnVarLenBuf[slati].nValue = nVal;
- }
- u_intslot * PUserDefnBuf()
- {
- return m_prgnVarLenBuf;
- }
-
- GrSlotState * CompRef(int slati)
- {
- Assert(slati < m_cnCompPerLig);
- return m_prgnVarLenBuf[m_cnUserDefn + slati].pslot;
- }
- void SetCompRef(int slati, GrSlotState * pvSlot)
- {
- Assert(slati < m_cnCompPerLig);
- m_prgnVarLenBuf[m_cnUserDefn + slati].pslot = pvSlot;
- }
- u_intslot * PCompRefBuf()
- {
- return m_prgnVarLenBuf + m_cnUserDefn;
- }
-
- int Slati(int i)
- {
- Assert(i < m_cnCompPerLig);
- return m_prgnVarLenBuf[m_cnUserDefn + m_cnCompPerLig + i].nValue;
- }
- void SetSlati(int i, int n)
- {
- Assert(i < m_cnCompPerLig);
- m_prgnVarLenBuf[m_cnUserDefn + m_cnCompPerLig + i].nValue = n;
- }
- u_intslot * PSlatiBuf()
- {
- return m_prgnVarLenBuf + m_cnUserDefn + m_cnCompPerLig;
- }
-
- int FeatureValue(int i)
- {
- Assert(i < m_cnFeat);
- return m_prgnVarLenBuf[m_cnUserDefn + (m_cnCompPerLig * 2) + i].nValue;
- }
-
- u_intslot * PFeatureBuf()
- {
- return m_prgnVarLenBuf + m_cnUserDefn + (m_cnCompPerLig * 2);
- }
-
- int CExtraSpace()
- {
- return m_cnUserDefn + (m_cnCompPerLig * 2) + m_cnFeat;
- }
-
// Needed for GlyphInfo:
float XPosition()
{
@@ -301,51 +147,18 @@ protected:
gid16 m_chwGlyphID;
gid16 m_chwActual; // actual glyph to output (which is a different glyph for pseudos)
- int m_islotPosPass; // index of slot in positioning streams, relative to first official
- // slot in the segment (possibly the LB slot)
-
- int m_spsl; // special slot flag: LB, bidi marker
+ sdata8 m_spsl; // special slot flag: LB, bidi marker
// bool m_fInitialLB; // for LB slots: true if this is the initial LB;
// false if it is the terminating LB
// TODO: remove
- int m_dirc; // default = kNotYetSet (read from glyph attr)
- int m_lb; // default = kNotYetSet (read from glyph attr)
-
- int m_nDirLevel;
-
- // raw glyph metrics (directly from font)
- float m_xysFontAscent;
- float m_xysFontDescent;
- float m_xysGlyphWidth;
- float m_xysGlyphHeight;
- float m_xysGlyphX;
- float m_xysGlyphY;
- float m_xysAdvX;
- float m_xysAdvY;
-
- // Slot attributes:
- short m_mAdvanceX;
- short m_mAdvanceY;
- short m_mShiftX;
- short m_mShiftY;
+ sdata8 m_dirc; // default = kNotYetSet8 (read from glyph attr)
+ sdata8 m_lb; // default = kNotYetSet8 (read from glyph attr)
- short m_srAttachTo;
- short m_nAttachLevel;
-
- short m_mAttachAtX;
- short m_mAttachAtY;
- short m_mAttachAtXOffset;
- short m_mAttachAtYOffset;
- short m_mAttachWithX;
- short m_mAttachWithY;
- short m_mAttachWithXOffset;
- short m_mAttachWithYOffset;
-
- short m_nAttachAtGpoint;
- short m_nAttachWithGpoint;
+ sdata8 m_nDirLevel;
+ // Slot attributes that are used by GrSlotOutput:
short m_mMeasureSol;
short m_mMeasureEol;
@@ -357,15 +170,9 @@ protected:
bool m_fInsertBefore; // default = true
- bool m_fHasComponents; // default = false
-
- bool m_fIsSpace;
-
- byte m_bStyleIndex;
+ sdata8 m_bIsSpace; // 0 = false, 1 = true, -1 = unknown
- byte m_cnUserDefn;
byte m_cnCompPerLig;
- byte m_cnFeat;
// There is a large block managed by either the GrTableManager (for GrSlotState)
// or the segment (for GrSlotOutput); this variable points at the sub-buffer for this
// particular slot:
@@ -374,10 +181,6 @@ protected:
float m_xsPositionX;
float m_ysPositionY;
-public: // for transduction logging
- bool m_fAdvXSet;
- bool m_fAdvYSet;
-
}; // end of class GrSlotAbstract
@@ -394,8 +197,8 @@ public: // for transduction logging
----------------------------------------------------------------------------------------------*/
class GrSlotState : public GrSlotAbstract
{
-
friend class GrSlotStream;
+ friend class FontMemoryUsage;
public:
enum { kNeutral = 99 };
@@ -423,6 +226,44 @@ public:
{
}
+ void BasicInitialize(int cnUserDefn, int cnCompPerLig, int cnFeat, u_intslot * pnBuf)
+ {
+ BasicInitializeAbstract(cnCompPerLig, pnBuf);
+
+ m_xysGlyphWidth = -1;
+ m_xysFontAscent = -1;
+ m_xysFontDescent = -1;
+
+ m_mAdvanceX = kNotYetSet;
+ m_mAdvanceY = kNotYetSet;
+ m_mShiftX = 0;
+ m_mShiftY = 0;
+
+ m_fAdvXSet = false; // for transduction logging
+ m_fAdvYSet = false;
+
+ m_srAttachTo = 0;
+ m_nAttachLevel = 0;
+
+ m_mAttachAtX = kNotYetSet;
+ m_mAttachAtY = 0;
+ m_nAttachAtGpoint = kNotYetSet;
+ m_mAttachAtXOffset = 0;
+ m_mAttachAtYOffset = 0;
+ m_mAttachWithX = kNotYetSet;
+ m_mAttachWithY = 0;
+ m_nAttachWithGpoint = kNotYetSet;
+ m_mAttachWithXOffset = 0;
+ m_mAttachWithYOffset = 0;
+
+ m_islotPosPass = kNotYetSet;
+
+ m_cnUserDefn = byte(cnUserDefn);
+ m_cnFeat = byte(cnFeat);
+
+ m_fHasComponents = false;
+ }
+
void Initialize(gid16 chw, GrEngine *, GrFeatureValues fval,
int ipass, int ichwSegOffset, int nUnicode = -1);
void Initialize(gid16 chw, GrEngine *, GrSlotState * pslotFeat,
@@ -434,6 +275,8 @@ public:
void CopyFeaturesFrom(GrSlotState * pslotSrc);
void FixAttachmentTree(GrSlotState * pslotOld);
+ void CopyFrom(GrSlotState * pslot, bool fCopyEverything = true);
+
// General:
int RawSegOffset() { return m_ichwSegOffset; }
@@ -442,13 +285,52 @@ public:
m_chwGlyphID = chw;
m_chwActual = kInvalidGlyph;
m_xysGlyphWidth = -1; // indicate glyph metrics are invalid
+ m_ipassFsmCol = -1;
+ m_colFsm = -1;
+ }
+
+ int PosPassIndex()
+ {
+ return m_islotPosPass;
+ }
+ void SetPosPassIndex(int islot, bool fInputToPosPass1)
+ {
+ // If we're resetting it, it should be to the same value as before:
+ Assert(fInputToPosPass1 || m_islotPosPass == kNotYetSet || m_islotPosPass == islot);
+ m_islotPosPass = islot;
+ }
+ void IncPosPassIndex()
+ {
+ m_islotPosPass++;
+ }
+ void ZapPosPassIndex()
+ {
+ m_islotPosPass = kNotYetSet;
}
+
+ int StyleIndex() { return m_bStyleIndex; }
+
+ int AttachTo() { return m_srAttachTo; }
+ int AttachLevel() { return m_nAttachLevel; }
+
+ int RawAttachAtX() { return m_mAttachAtX; }
+ int AttachAtY() { return m_mAttachAtY; }
+ int AttachAtGpoint() { return m_nAttachAtGpoint; }
+ int AttachAtXOffset() { return m_mAttachAtXOffset; }
+ int AttachAtYOffset() { return m_mAttachAtYOffset; }
+
+ int RawAttachWithX() { return m_mAttachWithX; }
+ int AttachWithY() { return m_mAttachWithY; }
+ int AttachWithGpoint() { return m_nAttachWithGpoint; }
+ int AttachWithXOffset() { return m_mAttachWithXOffset; }
+ int AttachWithYOffset() { return m_mAttachWithYOffset; }
+
void Associate(GrSlotState *);
void Associate(GrSlotState *, GrSlotState *);
void Associate(std::vector<GrSlotState*> &);
void ClearAssocs();
- int AssocsSize() { return m_vpslotAssoc.size(); }
+ int AssocsSize() { return m_vpslotAssoc.size(); }
GrSlotState * RawBeforeAssocSlot()
{
if (m_vpslotAssoc.size() == 0)
@@ -518,10 +400,12 @@ public:
return false;
}
+ bool HasComponents() { return m_fHasComponents; }
+
// Directionality as determined by the bidi algorithm
DirCode DirProcessed() // return the value
{
- Assert(m_dirc != kNotYetSet);
+ Assert(m_dirc != kNotYetSet8);
if (m_dircProc == kdircUnknown)
m_dircProc = DirCode(m_dirc);
return m_dircProc;
@@ -539,6 +423,11 @@ public:
m_fDirProcessed = true;
}
+ int RawAdvanceX() { return m_mAdvanceX; }
+ int RawAdvanceY() { return m_mAdvanceY; }
+ int ShiftX() { return m_mShiftX; }
+ int ShiftY() { return m_mShiftY; }
+
// Slot attributes that must be calculated:
int AdvanceX(GrTableManager * ptman)
@@ -618,10 +507,16 @@ public:
Assert(mVal < 0xFFFF); m_mAdvanceY = short(mVal & 0xFFFF); m_fShiftMod = true;
m_fAdvYSet = true; // for transduction logging
}
- void SetShiftX(int mVal) {
- Assert(mVal < 0xFFFF); m_mShiftX = short(mVal & 0xFFFF); m_fShiftMod = true; }
- void SetShiftY(int mVal) {
- Assert(mVal < 0xFFFF); m_mShiftY = short(mVal & 0xFFFF); m_fShiftMod = true; }
+ void SetShiftX(int mVal)
+ {
+ Assert(mVal < 0xFFFF); m_mShiftX = short(mVal & 0xFFFF);
+ m_fShiftMod = true;
+ }
+ void SetShiftY(int mVal)
+ {
+ Assert(mVal < 0xFFFF); m_mShiftY = short(mVal & 0xFFFF);
+ m_fShiftMod = true;
+ }
void SetAttachTo(int srVal)
{
@@ -660,11 +555,11 @@ public:
void SetCompRefSlot(GrTableManager * ptman, int i, GrSlotState * pslotComp);
- void SetBreakWeight(int lb) { m_lb = lb; }
+ void SetBreakWeight(int lb) { m_lb = sdata8(lb); }
void SetInsertBefore(bool f) { m_fInsertBefore = f; }
- void SetDirectionality(DirCode dirc) { m_dirc = dirc; }
- void SetDirLevel(int n) { m_nDirLevel = n; }
+ void SetDirectionality(DirCode dirc) { m_dirc = sdata8(dirc); }
+ void SetDirLevel(int n) { m_nDirLevel = sdata8(n); }
void SetMeasureSol(int mVal) { m_mMeasureSol = short(mVal); }
void SetMeasureEol(int mVal) { m_mMeasureEol = short(mVal); }
@@ -862,6 +757,96 @@ public:
bool IsLrm();
bool IsRlm();
+ // Cache of FSM column information for the most recent pass:
+ int FsmColumn() { return m_colFsm; }
+ int PassNumberForColumn() { return m_ipassFsmCol; }
+ void CacheFsmColumn(int ipass, int col)
+ {
+ m_colFsm = col;
+ m_ipassFsmCol = ipass;
+ }
+
+ // Variable-length buffer--includes four sub-buffers:
+ // * user-defined variables
+ // * component.???.ref assignments
+ // * mapping from components used to global attribute IDs for components
+ // * feature values
+
+ // user-defined slot attributes
+ int UserDefn(int slati)
+ {
+ Assert(slati < m_cnUserDefn);
+ return m_prgnVarLenBuf[slati].nValue;
+ }
+ void SetUserDefn(int slati, int nVal)
+ {
+ Assert(slati < m_cnUserDefn);
+ m_prgnVarLenBuf[slati].nValue = nVal;
+ }
+ u_intslot * PUserDefnBuf()
+ {
+ return m_prgnVarLenBuf;
+ }
+
+ // pointer to the associated slot which is the value of the comp.ref attribute
+ GrSlotState * CompRef(int slati)
+ {
+ Assert(slati < m_cnCompPerLig);
+ return m_prgnVarLenBuf[m_cnUserDefn + slati].pslot;
+ }
+ void SetCompRef(int slati, GrSlotState * pvSlot)
+ {
+ Assert(slati < m_cnCompPerLig);
+ m_prgnVarLenBuf[m_cnUserDefn + slati].pslot = pvSlot;
+ }
+ u_intslot * PCompRefBuf()
+ {
+ return m_prgnVarLenBuf + m_cnUserDefn;
+ }
+
+ // global component identifier
+ int Slati(int i)
+ {
+ Assert(i < m_cnCompPerLig);
+ return m_prgnVarLenBuf[m_cnUserDefn + m_cnCompPerLig + i].nValue;
+ }
+ void SetSlati(int i, int n)
+ {
+ Assert(i < m_cnCompPerLig);
+ m_prgnVarLenBuf[m_cnUserDefn + m_cnCompPerLig + i].nValue = n;
+ }
+ u_intslot * PSlatiBuf()
+ {
+ return m_prgnVarLenBuf + m_cnUserDefn + m_cnCompPerLig;
+ }
+
+ // feature settings
+ int FeatureValue(int i)
+ {
+ Assert(i < m_cnFeat);
+ return m_prgnVarLenBuf[m_cnUserDefn + (m_cnCompPerLig * 2) + i].nValue;
+ }
+
+ u_intslot * PFeatureBuf()
+ {
+ return m_prgnVarLenBuf + m_cnUserDefn + (m_cnCompPerLig * 2);
+ }
+
+ int CExtraSpace()
+ {
+ return m_cnUserDefn + (m_cnCompPerLig * 2) + m_cnFeat;
+ }
+
+ GrSlotState * CompRefSlot(int i);
+
+ void GetFeatureValues(GrFeatureValues * pfval)
+ {
+ pfval->m_nStyleIndex = m_bStyleIndex;
+ std::fill(pfval->m_rgnFValues, pfval->m_rgnFValues + kMaxFeatures, 0);
+ for (size_t i = 0; i < m_cnFeat; i++)
+ pfval->m_rgnFValues[i] = PFeatureBuf()[i].nValue;
+ }
+
// For transduction logging:
#ifdef TRACING
void SlotAttrsModified(bool * rgfMods, bool fPreJust, int * pccomp, int * pcassoc);
@@ -876,7 +861,6 @@ public:
protected:
// Instance variables:
-
int m_ipassModified; // pass in which this slot was modified
GrSlotState * m_pslotPrevState;
@@ -885,7 +869,11 @@ protected:
// underlying text relative to the official
// beginning of the segment;
// should == kInvalid for other slot states
- int m_nUnicode;; // for debugging
+ int m_islotPosPass; // index of slot in positioning streams, relative to first official
+ // slot in the segment (possibly the LB slot)
+
+ int m_colFsm; // which FSM column this glyph corresponds to...
+ int m_ipassFsmCol; // ...for the most recent pass
std::vector<GrSlotState*> m_vpslotAssoc; // association mappings
@@ -893,9 +881,47 @@ protected:
// default, rather than them being set explicitly
// within a rule
+ int m_nUnicode; // for debugging
+
DirCode m_dircProc; // directionality as processed in bidi algorithm
bool m_fDirProcessed;
+ // affects length of variable-length buffer
+ byte m_cnUserDefn;
+ byte m_cnFeat;
+
+ byte m_bStyleIndex;
+
+ // Slot attributes:
+ short m_mAdvanceX;
+ short m_mAdvanceY;
+ short m_mShiftX;
+ short m_mShiftY;
+
+ short m_srAttachTo;
+ short m_nAttachLevel;
+
+ short m_mAttachAtX;
+ short m_mAttachAtY;
+ short m_mAttachAtXOffset;
+ short m_mAttachAtYOffset;
+ short m_mAttachWithX;
+ short m_mAttachWithY;
+ short m_mAttachWithXOffset;
+ short m_mAttachWithYOffset;
+
+ short m_nAttachAtGpoint;
+ short m_nAttachWithGpoint;
+
+ // Raw glyph metrics (directly from font)
+ float m_xysFontAscent;
+ float m_xysFontDescent;
+ float m_xysGlyphWidth;
+ float m_xysGlyphHeight;
+ float m_xysGlyphX;
+ float m_xysGlyphY;
+ float m_xysAdvX;
+ float m_xysAdvY;
// Attachment and metrics
@@ -939,9 +965,12 @@ protected:
float m_xsRootShiftX;
float m_ysRootShiftY;
+ bool m_fHasComponents; // default = false
// Private methods:
+ void CopyAbstractFrom(GrSlotState * pslot);
+
void AdjustRootMetrics(GrTableManager * ptman, GrSlotStream *);
void InitMetrics(GrTableManager * ptman, GrSlotState * pslotRoot);
void InitLeafMetrics(GrTableManager * ptman, GrSlotState * pslotRoot);
@@ -998,6 +1027,10 @@ protected:
}
}
+public: // for transduction logging
+ bool m_fAdvXSet;
+ bool m_fAdvYSet;
+
}; // end of class GrSlotState
@@ -1011,18 +1044,21 @@ class GrSlotOutput : public GrSlotAbstract
{
friend class GlyphInfo;
friend class Segment;
+ friend class SegmentMemoryUsage;
public:
GrSlotOutput()
{
m_cComponents = 0;
m_isloutClusterBase = -1; // not part of any cluster
+ m_disloutCluster = 0;
m_igbb = -1;
- m_visloutClusterMembers.clear();
}
void ExactCopyFrom(GrSlotOutput * pslout, u_intslot * pnVarLenBuf, int cnExtraPerSlot);
+ void InitializeOutputFrom(GrSlotState * pslot);
+
int BeforeAssoc()
{
return m_ichwBeforeAssoc; // relative to the official beginning of the segment
@@ -1048,10 +1084,7 @@ public:
}
else
{
- // Must be kept consistent with UserDefn() and CompRef() methods inherited
- // from GrSlotAbstract. The component indices come after the above variable-
- // length buffers.
- m_prgnVarLenBuf[m_cnUserDefn + (m_cnCompPerLig * 2) + m_cnFeat + m_cComponents].nValue
+ m_prgnVarLenBuf[m_cComponents].nValue
= ichw;
// OBSOLETE comment:
@@ -1060,8 +1093,7 @@ public:
// have defined components a, b, and c, but only mapped a and c to actual
// characters. This buffer will then hold [0,2].
- m_prgnVarLenBuf[m_cnUserDefn + (m_cnCompPerLig * 2) + m_cnFeat
- + m_cnCompPerLig + m_cComponents].nValue
+ m_prgnVarLenBuf[m_cnCompPerLig + m_cComponents].nValue
= slati;
// Assert(iComp >= m_cComponents); // because we process them in order they are defined
@@ -1079,24 +1111,22 @@ public:
int UnderlyingComponent(int iComp)
{
Assert(iComp < m_cnCompPerLig);
- // Must be kept consistent with UserDefn() and CompRef() methods inherited
- // from GrSlotAbstract. The component indices come after the above variable-
- // length buffers.
- return m_prgnVarLenBuf[m_cnUserDefn + (m_cnCompPerLig * 2) + m_cnFeat + iComp].nValue;
+ return m_prgnVarLenBuf[iComp].nValue;
}
int ComponentId(int iComp)
{
- return m_prgnVarLenBuf[m_cnUserDefn + (m_cnCompPerLig * 2) + m_cnFeat
- + m_cnCompPerLig + iComp].nValue;
+ return m_prgnVarLenBuf[m_cnCompPerLig + iComp].nValue;
}
- // Given the index of the component used by the rules, indicate the
- // corresponding component as defined by the glyph attributes.
-// int DefinedComponent(int iCompUsed)
-// {
-// return m_prgnVarLenBuf[m_cnUserDefn + m_cnCompPerLig + m_cnFeat
-// + m_cnUserDefn + iCompUsed];
-// }
+ //u_intslot * PCompRefBufSlout()
+ //{
+ // return m_prgnVarLenBuf;
+ //}
+
+ int CExtraSpaceSlout()
+ {
+ return (m_cnCompPerLig * 2);
+ }
void SetClusterBase(int islout)
{
@@ -1110,22 +1140,28 @@ public:
bool IsPartOfCluster()
{
- return m_isloutClusterBase > -1;
+ return (m_isloutClusterBase > -1);
}
- int NumClusterMembers()
- {
- return m_visloutClusterMembers.size();
- }
+ //int NumClusterMembers()
+ //{
+ // return m_visloutClusterMembers.size();
+ //}
+ //int ClusterMember(int iislout)
+ //{
+ // return m_visloutClusterMembers[iislout];
+ //}
- int ClusterMember(int iislout)
+ void AddClusterMember(int isloutThis, int isloutAttached)
{
- return m_visloutClusterMembers[iislout];
+ m_disloutCluster = sdata8(max(int(m_disloutCluster), abs(isloutThis - isloutAttached)));
}
- void AddClusterMember(int islout)
+ void ClusterMembers(Segment * pseg, int islout, std::vector<int> & visloutRet);
+
+ int ClusterRange()
{
- m_visloutClusterMembers.push_back(islout);
+ return m_disloutCluster;
}
float ClusterXOffset() { return m_xsClusterXOffset; }
@@ -1134,11 +1170,24 @@ public:
void SetClusterAdvance(float xs) { m_xsClusterAdvance = xs; }
float GlyphMetricLogUnits(Font * pfont, int nGlyphMetric);
- float GlyphMetricLogUnits(int nMetricID);
+ //float GlyphMetricLogUnits(int nMetricID);
int GlyphBbIndex() { return m_igbb; }
void SetGlyphBbIndex (int i) { m_igbb = i; }
+ Rect BoundingBox(Font & font)
+ {
+ Rect rectBB;
+ rectBB.left = m_xsPositionX + GlyphMetricLogUnits(&font, kgmetBbLeft);
+ if (IsSpace())
+ rectBB.right = m_xsPositionX + GlyphMetricLogUnits(&font, kgmetAdvWidth);
+ else
+ rectBB.right = m_xsPositionX + GlyphMetricLogUnits(&font, kgmetBbRight);
+ rectBB.top = m_ysPositionY + GlyphMetricLogUnits(&font, kgmetBbTop);
+ rectBB.bottom = m_ysPositionY + GlyphMetricLogUnits(&font, kgmetBbBottom);
+ return rectBB;
+ }
+
bool IsLineBreak()
{
return (IsInitialLineBreak() || IsFinalLineBreak());
@@ -1152,22 +1201,18 @@ public:
return (m_spsl == kspslLbFinal);
}
- float AdvanceXMetric()
- {
- return m_xysAdvX;
- }
- bool IsSpace();
+ //float AdvanceXMetric()
+ //{
+ // return m_xysAdvX;
+ //}
- int CExtraSpaceSlout()
- {
- return m_cnUserDefn + (m_cnCompPerLig * 2) + m_cnFeat + (m_cnCompPerLig * 2);
- }
+ bool IsSpace();
void AdjustPosXBy(float dxs)
{
m_xsPositionX += dxs;
- m_rectBB.left += dxs;
- m_rectBB.right += dxs;
+ //m_rectBB.left += dxs;
+ //m_rectBB.right += dxs;
}
void ShiftForDirDepthChange(float dxsSegWidth);
@@ -1188,20 +1233,21 @@ public:
protected:
// Instance variables:
- int m_ichwBeforeAssoc; // index of associated character in the string
- int m_ichwAfterAssoc; // (relative to the official beginning of the segment)
- // char might possibly not be officially in this segment
-
- int m_cComponents;
+ sdata8 m_cComponents;
- std::vector<int> m_visloutClusterMembers; // indices (logical surface position)
- // of other slots that have this cluster as
- // its base (absolute root), not necessarily sorted;
- // does not include self
+ data8 m_disloutCluster; // how far to search on either side of this glyph to find
+ // other members of the cluster;
+ // 0 means there are no cluster members or this glyph is
+ // attached to some other base
int m_isloutClusterBase; // the index of the slot that serves as the base for the
// cluster this slot is a part of; -1 if not part of cluster
+ int m_ichwBeforeAssoc; // index of associated character in the string
+ int m_ichwAfterAssoc; // (relative to the official beginning of the segment)
+ // char might possibly not be officially in this segment,
+ // in which case value is infinity
+
// Measurements for highlighting an entire cluster, relative to origin of this slot,
// which is the cluster base.
float m_xsClusterXOffset;
@@ -1211,8 +1257,8 @@ protected:
int m_igbb;
float m_xsAdvanceX;
- float m_ysAdvanceY;
- Rect m_rectBB;
+// float m_ysAdvanceY; -- not used
+// Rect m_rectBB;
}; // end of class GrSlotOutput
diff --git a/Build/source/libs/graphite-engine/src/segment/GrSlotStream.cpp b/Build/source/libs/graphite-engine/src/segment/GrSlotStream.cpp
index b6ca2e599b4..f71aefdee3a 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrSlotStream.cpp
+++ b/Build/source/libs/graphite-engine/src/segment/GrSlotStream.cpp
@@ -1610,7 +1610,7 @@ void GrSlotStream::AppendLineBreak(GrTableManager * ptman, GrCharStream * pchstr
pengst->NewSlot(ptman->LBGlyphID(), fval, 0, ichwSegOffset, -1, &pslotNew);
}
- pslotNew->m_lb = lb;
+ pslotNew->m_lb = sdata8(lb);
pslotNew->SetSpecialSlotFlag(fInitial ? kspslLbInitial : kspslLbFinal);
//pslotNew->m_fInitialLB = fInitial; // TODO: remove
pslotNew->SetDirectionality(dirc);
diff --git a/Build/source/libs/graphite-engine/src/segment/GrSlotStream.h b/Build/source/libs/graphite-engine/src/segment/GrSlotStream.h
index fd35d50c0d0..006191252dc 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrSlotStream.h
+++ b/Build/source/libs/graphite-engine/src/segment/GrSlotStream.h
@@ -88,6 +88,7 @@ class Font;
class GrSlotStream {
friend class GrSlotState;
+ friend class FontMemoryUsage;
public:
// Constructor:
diff --git a/Build/source/libs/graphite-engine/src/segment/GrTableManager.cpp b/Build/source/libs/graphite-engine/src/segment/GrTableManager.cpp
index 1e5a1aa2846..dfb49717946 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrTableManager.cpp
+++ b/Build/source/libs/graphite-engine/src/segment/GrTableManager.cpp
@@ -347,7 +347,7 @@ void GrTableManager::Run(Segment * psegNew, Font * pfont,
m_fLogging = (pstrmLog != NULL);
int cbPrev;
- byte * pbPrevSegDat;
+ byte * pbPrevSegDat = NULL;
if (psegPrev)
cbPrev = psegPrev->NextSegInitBuffer(&pbPrevSegDat);
else if (psegInit)
@@ -493,7 +493,7 @@ void GrTableManager::Run(Segment * psegNew, Font * pfont,
{
// Nothing will fit. Initialize the new segment just enough so that
// we can delete it.
- InitSegmentToDelete(psegNew);
+ InitSegmentToDelete(psegNew, pfont, pchstrm);
return;
}
}
@@ -730,14 +730,14 @@ void GrTableManager::InitNewSegment(Segment * psegNew,
{
// Invalid empty segment.
Assert(ichwMin == ichwLim);
- InitSegmentToDelete(psegNew);
+ InitSegmentToDelete(psegNew, pfont, pchstrm);
}
return;
}
Assert(psegNew);
- psegNew->Initialize(pchstrm->String(),
+ psegNew->Initialize(pchstrm->TextSrc(),
ichwMin, ichwLim,
lbStart, lbEnd, est, fStartLine, fEndLine, m_pgreng->RightToLeft());
@@ -761,10 +761,18 @@ void GrTableManager::InitNewSegment(Segment * psegNew,
couldn't find a valid break point. Initialize it just enough so that it can be
deleted by the client.
----------------------------------------------------------------------------------------------*/
-void GrTableManager::InitSegmentToDelete(Segment * psegNew)
+void GrTableManager::InitSegmentToDelete(Segment * psegNew, Font * pfont,
+ GrCharStream * pchstrm)
{
- psegNew->Initialize(NULL, 0, 0, klbClipBreak, klbClipBreak, kestNothingFit,
- false, false, false);
+ psegNew->Initialize(pchstrm->TextSrc(), 0, 0,
+ klbClipBreak, klbClipBreak, kestNothingFit, false, false,
+ m_pgreng->RightToLeft());
+
+ psegNew->SetEngine(m_pgreng);
+ psegNew->SetFont(pfont);
+ psegNew->SetJustifier(NULL); // can't justify an empty segment
+ psegNew->SetFaceName(m_pgreng->FaceName(), m_pgreng->BaseFaceName());
+ psegNew->SetPreContext(0);
}
/*----------------------------------------------------------------------------------------------
@@ -877,7 +885,7 @@ void GrTableManager::InitSegmentAsEmpty(Segment * psegNew, Font * pfont,
Assert(psegNew);
- psegNew->Initialize(pchstrm->String(), ichwMin, ichwLim,
+ psegNew->Initialize(pchstrm->TextSrc(), ichwMin, ichwLim,
lbStart, lbEnd, kestNoMore, fStartLine, fEndLine, m_pgreng->RightToLeft());
psegNew->SetEngine(m_pgreng);
@@ -890,18 +898,15 @@ void GrTableManager::InitSegmentAsEmpty(Segment * psegNew, Font * pfont,
int * pcbNextSegDat = &cbNextSegDat;
// Initialization for (theoretical) next segment.
- if (pbNextSegDat)
- {
- byte * pb = pbNextSegDat;
- *pb++ = byte(lbEnd);
- *pb++ = kdircNeutral;
- *pb++ = kdircNeutral;
+ byte * pb = pbNextSegDat;
+ *pb++ = byte(lbEnd);
+ *pb++ = kdircNeutral;
+ *pb++ = kdircNeutral;
+ *pb++ = 0;
+ for (int ipass = 0; ipass < m_cpass; ipass++)
*pb++ = 0;
- for (int ipass = 0; ipass < m_cpass; ipass++)
- *pb++ = 0;
- *pcbNextSegDat = 0;
- psegNew->RecordInitializationForNextSeg(*pcbNextSegDat, pbNextSegDat);
- }
+ *pcbNextSegDat = 0;
+ psegNew->RecordInitializationForNextSeg(*pcbNextSegDat, pbNextSegDat);
psegNew->SetPreContext(0);
}
@@ -931,11 +936,12 @@ bool GrTableManager::Backtrack(int * pislotPrevBreak,
LineBrk * plbFound)
{
int islotStartTry;
- if (*pislotPrevBreak == ichwCallerBtLim - 1)
- {
- islotStartTry = *pislotPrevBreak;
- }
- else if (*pislotPrevBreak == -1)
+ //if (*pislotPrevBreak == ichwCallerBtLim - 1)
+ //{
+ // islotStartTry = *pislotPrevBreak;
+ //}
+ //else
+ if (*pislotPrevBreak == -1)
{
// If no line break has been found so far, figure out where to start trying based
// on where the final stream choked.
@@ -956,6 +962,10 @@ bool GrTableManager::Backtrack(int * pislotPrevBreak,
else
islotStartTry = *pislotPrevBreak - 1; // skip previous slot
}
+ if (ichwCallerBtLim > -1 && islotStartTry > ichwCallerBtLim - 1)
+ {
+ islotStartTry = ichwCallerBtLim - 1;
+ }
// Determine if we want to insert an actual line-break "glyph". Don't do that if
// we are omitting trailing white space or we are at a writing-system or font break.
@@ -985,7 +995,7 @@ bool GrTableManager::Backtrack(int * pislotPrevBreak,
Assert(*plbMin <= lbMax);
GrSlotStream * psstrmLB = OutputStream(m_cpassLB);
islotStartTry = min(islotStartTry, psstrmLB->WritePos() - 1);
- int islotNewBreak;
+ int islotNewBreak = -1;
while (lb <= lbMax)
{
LineBrk lbNextToTry;
@@ -1119,17 +1129,6 @@ void GrTableManager::InitializeForNextSeg(Segment * pseg,
std::vector<int> vcslotSkipOffsets;
vcslotSkipOffsets.resize(m_cpass);
- if (cbNextMax == 0 || !pbNextSegDat)
- {
- // Caller is not interested in cross-line-boundary contextualization.
- Assert(cbNextMax == 0);
- Assert(!pbNextSegDat);
- return;
- }
-
- if (cbNextMax < m_cpass + 4)
- THROW(kresInvalidArg);
-
byte * pb = pbNextSegDat;
if (!fNextSegNeedsContext)
@@ -1198,8 +1197,8 @@ void GrTableManager::InitializeForNextSeg(Segment * pseg,
if (ipass >= m_cpassLB && m_engst.m_fInitialLB)
islotBackupMin++; // how far we can back up--not before the start of this segment
- int islotPrevRS; // corresponding slot in the previous stream for rule-start position
- int islotPrevPC; // same for pre-context position
+ int islotPrevRS = 0; // corresponding slot in the previous stream for rule-start position
+ int islotPrevPC = 0; // same for pre-context position
// Initially we have to include at least this many prior slots:
int cslotSkipOffset = 0;
@@ -1406,6 +1405,7 @@ void GrTableManager::CalculateAssociations(Segment * pseg, int csloutSurface)
}
AdjustAssocsForOverlaps(pseg);
+ pseg->CleanUpAssocsVectors();
// pseg->AdjustForOverlapsWithPrevSeg(); // for any characters officially in the
// previous segment but rendered in this one,
@@ -1774,7 +1774,7 @@ void EngineState::NextSlot(GrSlotState ** ppslotRet)
}
*ppslotRet = m_vslotblk[m_islotblkCurr] + m_islotNext;
- (*ppslotRet)->GrSlotAbstract::BasicInitialize(m_cUserDefn, m_cCompPerLig, m_cFeat,
+ (*ppslotRet)->BasicInitialize(m_cUserDefn, m_cCompPerLig, m_cFeat,
(m_vprgnSlotVarLenBufs[m_islotblkCurr] + (m_islotNext * cnExtraPerSlot)));
m_islotNext++;
}
@@ -2481,7 +2481,7 @@ void GrTableManager::CalcPositionsUpTo(int ipass, GrSlotState * pslotLast,
// Only do this for slots that have actually been processed by the final
// pass, because others may have intermediate values that may be changed
// later.
- m_engst.m_islotPosNext = pslotLastBase->PosPassIndex() + psstrm->IndexOffset() + 1;
+ m_engst.m_islotPosNext = pslot->PosPassIndex() + psstrm->IndexOffset() + 1;
m_engst.m_xsPosXNext = xs;
m_engst.m_ysPosYNext = ys;
m_engst.m_dxsTotWidthSoFar = *pxsWidth;
diff --git a/Build/source/libs/graphite-engine/src/segment/GrTableManager.h b/Build/source/libs/graphite-engine/src/segment/GrTableManager.h
index b19ca8deb5a..b0ab1e819d1 100644
--- a/Build/source/libs/graphite-engine/src/segment/GrTableManager.h
+++ b/Build/source/libs/graphite-engine/src/segment/GrTableManager.h
@@ -34,6 +34,8 @@ class Font;
class EngineState
{
friend class GrTableManager;
+ friend class FontMemoryUsage;
+
public:
EngineState();
void Initialize(GrEngine *, GrTableManager *);
@@ -310,6 +312,7 @@ protected:
----------------------------------------------------------------------------------------------*/
class GrTableManager {
+ friend class FontMemoryUsage;
public:
// Constructor & destructor:
@@ -487,7 +490,7 @@ protected:
void InitSegmentAsEmpty(Segment * psegNew, Font * pfont, GrCharStream * pchstrm,
bool fStartLine, bool fEndLine);
- void InitSegmentToDelete(Segment * psegNew);
+ void InitSegmentToDelete(Segment * psegNew, Font * pfont, GrCharStream * pchstrm);
int ChunkInPrev(int ipass, int islot, GrCharStream * pchstrm);
diff --git a/Build/source/libs/graphite-engine/src/segment/Main.h b/Build/source/libs/graphite-engine/src/segment/Main.h
index def3d771c7b..5fed3be3973 100644
--- a/Build/source/libs/graphite-engine/src/segment/Main.h
+++ b/Build/source/libs/graphite-engine/src/segment/Main.h
@@ -22,9 +22,11 @@ Description:
#define NO_EXCEPTIONS 1
// It's okay to use functions that were declared deprecated by VS 2005:
+#ifdef _MSC_VER
#define _CRT_SECURE_NO_DEPRECATE
#pragma warning(disable: 4996) // warning: function was declared deprecated
#pragma warning(disable: 4702) // unreachable code
+#endif
#include "GrCommon.h"
@@ -150,11 +152,12 @@ struct Rect
#include "FontFace.h"
#include "Segment.h"
#include "SegmentPainter.h"
-#ifdef _WIN32
-#include <hash_map>
-#include "WinFont.h"
-#include "WinSegmentPainter.h"
-#endif
+
+//#ifdef _WIN32
+//#include <hash_map>
+//#include "WinFont.h"
+//#include "WinSegmentPainter.h"
+//#endif
// Internal headers
#include "TtfUtil.h"
diff --git a/Build/source/libs/graphite-engine/src/segment/Makefile.am b/Build/source/libs/graphite-engine/src/segment/Makefile.am
index ad5c107f668..59113aa924b 100644
--- a/Build/source/libs/graphite-engine/src/segment/Makefile.am
+++ b/Build/source/libs/graphite-engine/src/segment/Makefile.am
@@ -14,6 +14,7 @@ libgraphite_la_SOURCES += $(segmentdir)/GrPass.cpp
libgraphite_la_SOURCES += $(segmentdir)/GrSlotState.cpp
libgraphite_la_SOURCES += $(segmentdir)/GrSlotStream.cpp
libgraphite_la_SOURCES += $(segmentdir)/GrTableManager.cpp
+libgraphite_la_SOURCES += $(segmentdir)/MemoryUsage.cpp
libgraphite_la_SOURCES += $(segmentdir)/Platform.cpp
libgraphite_la_SOURCES += $(segmentdir)/SegmentAux.cpp
libgraphite_la_SOURCES += $(segmentdir)/Segment.cpp
@@ -22,5 +23,4 @@ libgraphite_la_SOURCES += $(segmentdir)/TestPasses.cpp
libgraphite_la_SOURCES += $(segmentdir)/TransductionLog.cpp
EXTRA_DIST += $(segmentdir)/*.h
-EXTRA_DIST += $(segmentdir)/explicit_instantiations.cpp
diff --git a/Build/source/libs/graphite-engine/src/segment/MemoryUsage.cpp b/Build/source/libs/graphite-engine/src/segment/MemoryUsage.cpp
new file mode 100644
index 00000000000..ac693b5b1d4
--- /dev/null
+++ b/Build/source/libs/graphite-engine/src/segment/MemoryUsage.cpp
@@ -0,0 +1,780 @@
+/*--------------------------------------------------------------------*//*:Ignore this sentence.
+Copyright (C) 1999, 2001 SIL International. All rights reserved.
+
+Distributable under the terms of either the Common Public License or the
+GNU Lesser General Public License, as specified in the LICENSING.txt file.
+
+File: MemoryUsage.cpp
+Responsibility: Sharon Correll
+Last reviewed: Not yet.
+
+Description:
+ Calculates memory usage for the engine and segments.
+----------------------------------------------------------------------------------------------*/
+
+#pragma warning(disable: 4244) // conversion from wchar_t to char
+#pragma warning(disable: 4702) // unreachable code
+
+//:>********************************************************************************************
+//:> Include files
+//:>********************************************************************************************
+
+#include "GrCommon.h"
+#include "GrData.h"
+#ifndef _WIN32
+#include "GrMstypes.h"
+#endif
+#include "GrDebug.h"
+//#include <fstream>
+#include <iostream>
+//#include <string>
+// Forward declarations.
+
+#include "Main.h"
+
+//namespace gr
+//{
+// class GrTableManager;
+// class Segment;
+// class GrEngine;
+//}
+//
+//#include "GrTableManager.h"
+//#include "GrFeatureValues.h"
+//#include "GrSlotState.h"
+//#include "SegmentAux.h"
+//#include "Segment.h"
+#include "MemoryUsage.h"
+
+//#ifndef _MSC_VER
+//#include "config.h"
+//#endif
+
+#ifdef _MSC_VER
+#pragma hdrstop
+#endif
+#undef THIS_FILE
+DEFINE_THIS_FILE
+
+//:End Ignore
+
+//:>********************************************************************************************
+//:> Forward declarations
+//:>********************************************************************************************
+
+//:>********************************************************************************************
+//:> Local Constants and static variables
+//:>********************************************************************************************
+
+const int stringOverhead = (3 * sizeof(int)) + (sizeof(void *)) + (8 * sizeof(short));
+const int vectorOverhead = 3 * sizeof(void *);
+
+namespace gr
+{
+
+//:>********************************************************************************************
+//:> Font/engine
+//:>********************************************************************************************
+
+void FontMemoryUsage::initialize()
+{
+ font = 0;
+ fontCache = 0;
+ fontFace = 0;
+
+ eng_count = 0;
+ eng_overhead = 0;
+ eng_scalars = 0;
+ eng_strings = 0;
+ eng_pointers = 0;
+ eng_cmap = 0;
+ eng_nameTable = 0;
+
+ pseudoMap = 0;
+
+ clstbl_counters = 0;
+ clstbl_offsets = 0;
+ clstbl_glyphList = 0;
+
+ glftbl_general = 0;
+ glftbl_compDefns = 0;
+ glftbl_attrTable = 0;
+ glftbl_attrOffsets = 0;
+
+ lngtbl_general = 0;
+ lngtbl_entries = 0;
+ lngtbl_featureSets = 0;
+
+ tman_general = 0;
+
+ pass_count = 0;
+ pass_general = 0;
+ pass_fsm = 0;
+ pass_ruleExtras = 0;
+ pass_constraintOffsets = 0;
+ pass_constraintCode = 0;
+ pass_actionOffsets = 0;
+ pass_actionCode = 0;
+
+ engst_general = 0;
+ engst_passState = 0;
+
+ sstrm_count = 0;
+ sstrm_general = 0;
+ sstrm_chunkMapsUsed = 0;
+ sstrm_chunkMapsAlloc = 0;
+ sstrm_reprocBuf = 0;
+
+ slot_count = 0;
+ slot_general = 0;
+ slot_abstract = 0;
+ slot_varLenBuf = 0;
+ slot_assocsUsed = 0;
+ slot_assocsAlloc = 0;
+ slot_attachUsed = 0;
+ slot_attachAlloc = 0;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return the total byte count.
+----------------------------------------------------------------------------------------------*/
+int FontMemoryUsage::total()
+{
+ int grandTotal = 0;
+ grandTotal += font + fontCache + fontFace;
+ grandTotal += eng_overhead + eng_scalars + eng_strings + eng_pointers + eng_cmap + eng_nameTable;
+ grandTotal += pseudoMap;
+ grandTotal += clstbl_counters + clstbl_offsets + clstbl_glyphList;
+ grandTotal += glftbl_general + glftbl_compDefns + glftbl_attrTable + glftbl_attrOffsets;
+ grandTotal += lngtbl_general + lngtbl_entries + lngtbl_featureSets;
+ grandTotal += tman_general;
+ grandTotal += pass_general + pass_fsm + pass_ruleExtras
+ + pass_constraintOffsets + pass_constraintCode + pass_actionOffsets + pass_actionCode;
+ grandTotal += engst_general + engst_passState;
+ grandTotal += sstrm_general + sstrm_chunkMapsAlloc + sstrm_reprocBuf;
+ grandTotal += slot_general + slot_abstract + slot_varLenBuf + slot_assocsAlloc + slot_attachAlloc;
+
+ return grandTotal;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Add the results of two runs together.
+----------------------------------------------------------------------------------------------*/
+void FontMemoryUsage::add(FontMemoryUsage & fmu)
+{
+ font += fmu.font;
+ fontCache += fmu.fontCache;
+ fontFace += fmu.fontFace;
+
+ eng_count += fmu.eng_count;
+ eng_overhead += fmu.eng_overhead;
+ eng_scalars += fmu.eng_scalars;
+ eng_strings += fmu.eng_strings;
+ eng_pointers += fmu.eng_pointers;
+ eng_cmap += fmu.eng_cmap;
+ eng_nameTable += fmu.eng_nameTable;
+
+ pseudoMap += fmu.pseudoMap;
+
+ clstbl_counters += fmu.clstbl_counters;
+ clstbl_offsets += fmu.clstbl_offsets;
+ clstbl_glyphList += fmu.clstbl_glyphList;
+
+ glftbl_general += fmu.glftbl_general;
+ glftbl_compDefns += fmu.glftbl_compDefns;
+ glftbl_attrTable += fmu.glftbl_attrTable;
+ glftbl_attrOffsets += fmu.glftbl_attrOffsets;
+
+ lngtbl_general += fmu.lngtbl_general;
+ lngtbl_entries += fmu.lngtbl_entries;
+ lngtbl_featureSets += fmu.lngtbl_featureSets;
+
+ tman_general += fmu.tman_general;
+
+ pass_count += fmu.pass_count;
+ pass_general += fmu.pass_general;
+ pass_fsm += fmu.pass_fsm;
+ pass_ruleExtras += fmu.pass_ruleExtras;
+ pass_constraintOffsets += fmu.pass_constraintOffsets;
+ pass_constraintCode += fmu.pass_constraintCode;
+ pass_actionOffsets += fmu.pass_actionOffsets;
+ pass_actionCode += fmu.pass_actionCode;
+
+ engst_general += fmu.engst_general;
+ engst_passState += fmu.engst_passState;
+
+ sstrm_count += fmu.sstrm_count;
+ sstrm_general += fmu.sstrm_general;
+ sstrm_chunkMapsUsed += fmu.sstrm_chunkMapsUsed;
+ sstrm_chunkMapsAlloc += fmu.sstrm_chunkMapsAlloc;
+ sstrm_reprocBuf += fmu.sstrm_reprocBuf;
+
+ slot_count += fmu.slot_count;
+ slot_general += fmu.slot_general;
+ slot_abstract += fmu.slot_abstract;
+ slot_varLenBuf += fmu.slot_varLenBuf;
+ slot_assocsUsed += fmu.slot_assocsUsed;
+ slot_assocsAlloc += fmu.slot_assocsAlloc;
+ slot_attachUsed += fmu.slot_attachUsed;
+ slot_attachAlloc += fmu.slot_attachAlloc;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Add up the memory used by all the engines in the cache.
+----------------------------------------------------------------------------------------------*/
+FontMemoryUsage Font::calculateMemoryUsage()
+{
+ FontMemoryUsage fmu;
+ FontFace::calculateAllMemoryUsage(fmu);
+ return fmu;
+}
+
+void FontFace::calculateAllMemoryUsage(FontMemoryUsage & fmu)
+{
+ s_pFontCache->calculateMemoryUsage(fmu);
+}
+
+void FontCache::calculateMemoryUsage(FontMemoryUsage & fmuTotal)
+{
+ fmuTotal.fontCache += sizeof(int) * 4; // m_cfci, m_cfciMax, m_cfface, m_flush
+ fmuTotal.fontCache += sizeof(void*); // m_prgfci;
+
+ // Iterate through all the font faces in the cache.
+ for (int ifci = 0; ifci < m_cfci; ifci++)
+ {
+ CacheItem * pfci = m_prgfci + ifci;
+ char rgchFontName[32];
+ memset(rgchFontName, 0, 32 * sizeof(char));
+ std::copy(pfci->szFaceName, pfci->szFaceName + 32, rgchFontName);
+ std::string strFontName(rgchFontName);
+ fmuTotal.vstrFontNames.push_back(strFontName);
+ int cface = 0;
+ if (pfci->pffaceRegular)
+ {
+ FontMemoryUsage fmu;
+ pfci->pffaceRegular->calculateMemoryUsage(fmu);
+ fmuTotal.add(fmu);
+ fmuTotal.vFontTotalsReg.push_back(fmu.total());
+ cface++;
+ }
+ else
+ fmuTotal.vFontTotalsReg.push_back(0);
+
+ if (pfci->pffaceBold)
+ {
+ FontMemoryUsage fmu;
+ pfci->pffaceBold->calculateMemoryUsage(fmu);
+ fmuTotal.add(fmu);
+ fmuTotal.vFontTotalsBold.push_back(fmu.total());
+ cface++;
+ }
+ else
+ fmuTotal.vFontTotalsBold.push_back(0);
+
+ if (pfci->pffaceItalic)
+ {
+ FontMemoryUsage fmu;
+ pfci->pffaceItalic->calculateMemoryUsage(fmu);
+ fmuTotal.add(fmu);
+ fmuTotal.vFontTotalsItalic.push_back(fmu.total());
+ cface++;
+ }
+ else
+ fmuTotal.vFontTotalsItalic.push_back(0);
+
+ if (pfci->pffaceBI)
+ {
+ FontMemoryUsage fmu;
+ pfci->pffaceBI->calculateMemoryUsage(fmu);
+ fmuTotal.add(fmu);
+ fmuTotal.vFontTotalsBI.push_back(fmu.total());
+ cface++;
+ }
+ else
+ fmuTotal.vFontTotalsBI.push_back(0);
+
+ fmuTotal.vFaceCount.push_back(cface);
+ }
+}
+
+void FontFace::calculateMemoryUsage(FontMemoryUsage & fmu)
+{
+ fmu.fontFace += sizeof(int); // m_cfonts
+ fmu.fontFace += sizeof(void *) * 2; // s_pFontCache, m_pgreng
+
+ fmu.font += m_cfonts * sizeof(void*); // m_pfface
+
+ fmu.addEngine(m_pgreng);
+}
+
+void FontMemoryUsage::addEngine(GrEngine * pgreng)
+{
+ eng_count++;
+
+ eng_overhead += sizeof(long); // m_cref
+ eng_scalars += sizeof(bool) * 6; // m_fBold, m_fItalic, m_fSmart...
+ eng_scalars += sizeof(bool) * 2; // m_fFakeItalicCache, m_fFakeBICache;
+ eng_strings += stringOverhead * 4; // m_strCtrlFileReg/Bold/Italic/BI
+ eng_strings += sizeof(wchar_t) * pgreng->m_strCtrlFileReg.length();
+ eng_strings += sizeof(wchar_t) * pgreng->m_strCtrlFileBold.length();
+ eng_strings += sizeof(wchar_t) * pgreng->m_strCtrlFileItalic.length();
+ eng_strings += sizeof(wchar_t) * pgreng->m_strCtrlFileBI.length();
+ eng_scalars += sizeof(bool);
+ eng_strings += stringOverhead * 6; // m_stuCtrlFile etc.
+ eng_strings += sizeof(wchar_t) * pgreng->m_stuCtrlFile.length();
+ eng_strings += sizeof(wchar_t) * pgreng->m_stuInitError.length();
+ eng_strings += sizeof(wchar_t) * pgreng->m_stuFaceName.length();
+ eng_strings += sizeof(wchar_t) * pgreng->m_stuFeatures.length();
+ eng_strings += sizeof(wchar_t) * pgreng->m_stuBaseFaceName.length();
+ eng_scalars += sizeof(bool); // m_fUseSepBase
+ eng_scalars += sizeof(GrResult) * 2; // m_resFontRead, m_resFontValid
+ eng_scalars += sizeof(FontErrorCode);
+ eng_scalars += sizeof(int) * 3; // m_fxdBadVersion, m_nFontCheckSum, m_nScriptTag, m_grfsdc
+ eng_scalars += sizeof(bool); // m_fRightToLeft
+ eng_scalars += sizeof(int) * 2; // m_mXAscent, m_mXDescent
+ eng_scalars += sizeof(float); // m_dysOffset
+ eng_scalars += sizeof(bool); // m_fBasicJust
+ eng_scalars += sizeof(int); // m_cJLevels
+ eng_pointers += sizeof(void*) * 4; // m_ptman, m_pctbl, m_pgtbl, m_pfface
+ eng_scalars += sizeof(GrFeature) * kMaxFeatures;
+ eng_scalars += sizeof(int); // m_cfeat
+ eng_scalars += sizeof(size_t); // m_clcidFeatLabelLangs
+ eng_scalars += sizeof(short) * pgreng->m_clcidFeatLabelLangs;
+ // m_langtbl
+ eng_scalars += sizeof(bool); // m_fLineBreak
+ eng_scalars += sizeof(int) * 2; // m_cchwPreXlbContext, m_cchwPostXlbContext
+ eng_scalars += sizeof(data16) * 7; // m_chwPseudoAttr, etc.
+ eng_scalars += sizeof(gid16); // m_chwLBGlyphID
+ eng_scalars += sizeof(int) * 4; // m_cComponents, m_cnUserDefn, m_cnCompPerLig, m_mFontEmUnits
+
+ pseudoMap += sizeof(int) * 3;
+ pseudoMap += sizeof(GrPseudoMap) * pgreng->m_cpsd;
+
+ eng_cmap += sizeof(void*) * 2;
+ eng_cmap += sizeof(byte*);
+ eng_cmap += sizeof(bool);
+ if (pgreng->m_fCmapTblCopy)
+ eng_cmap += pgreng->m_cbCmapTbl;
+
+ eng_nameTable += sizeof(byte *);
+ eng_nameTable += sizeof(bool);
+ if (pgreng->m_fNameTblCopy)
+ eng_nameTable += pgreng->m_cbNameTbl;
+
+ eng_scalars += sizeof(bool) * 2; // m_fLogXductn, m_fInErrorState
+
+ clstbl_counters += sizeof(int) * 2; // m_ccls, m_cclsLinear
+ clstbl_offsets += sizeof(data16) * (pgreng->m_pctbl->m_ccls + 1);
+ clstbl_glyphList += sizeof(data16) * (pgreng->m_pctbl->m_prgichwOffsets[pgreng->m_pctbl->m_ccls]);
+
+ glftbl_general += sizeof(int) * 3; // m_cglf, m_cComponents, m_cgstbl
+ glftbl_general += vectorOverhead; // m_vpgstbl
+ GrGlyphSubTable * pgstbl = pgreng->m_pgtbl->m_vpgstbl[0];
+ glftbl_general += sizeof(int) * 4; // m_fxdSilfVersion, m_nAttrIDLim, m_cComponents, m_cnCompPerLig
+ glftbl_general += sizeof(bool) * 2; // m_fHasDebugStrings, m_fGlocShort
+ glftbl_general += sizeof(data16) * 3; // m_chw...Attr
+ glftbl_compDefns += sizeof(int) * (pgstbl->m_cnCompPerLig + 1) * pgreng->m_pgtbl->m_cglf;
+ glftbl_attrTable += sizeof(int) * 2; // m_fxdSilfVersion, m_cbEntryBufLen
+ glftbl_attrTable += sizeof(byte) * pgstbl->m_pgatbl->m_cbEntryBufLen;
+ glftbl_attrOffsets +=
+ (pgreng->m_pgtbl->m_cglf + 1) * ((pgstbl->m_fGlocShort) ? sizeof(data16) : sizeof(data32));
+
+ lngtbl_general += sizeof(size_t); // m_clang
+ lngtbl_general += sizeof(data16) * 3; // m_dilangInit, m_cLoop, m_ilangStart
+ lngtbl_general += sizeof(void*) * 2; // m_prglang, m_prgfset
+ lngtbl_general += sizeof(int); // m_cbOffset0
+ lngtbl_entries += sizeof(GrLangTable::LangEntry) * pgreng->m_langtbl.m_clang;
+ lngtbl_featureSets += sizeof(GrLangTable::FeatSet) * pgreng->m_langtbl.m_cfset;
+
+ GrTableManager * ptman = pgreng->m_ptman;
+ tman_general += sizeof(int) * 4; // m_cpass, m_cpassLB, m_ipassPos1, m_ipassJust1
+ tman_general += sizeof(bool); // m_fBidi
+ tman_general += sizeof(void*) * 2; // m_prgppass, m_pgreng
+ tman_general += sizeof(void*) * ptman->m_cpass; // m_prgppass
+ tman_general += sizeof(bool); // m_fLogging
+
+ pass_count += ptman->m_cpass;
+ for (int ipass = 0; ipass < ptman->m_cpass; ipass++)
+ {
+ GrPass * ppass = ptman->m_prgppass[ipass];
+ pass_general = sizeof(GrPass);
+
+ GrFSM * pfsm = ppass->m_pfsm;
+ if (pfsm)
+ {
+ pass_fsm += sizeof(int) * 5; // m_crow, m_crowFinal, m_rowFinalMin, m_crowNonAcpt, m_ccol
+ pass_fsm += sizeof(void*) * 3; // m_prgirulnMin, m_prgrulnMatched, m_prgrowTransitions
+ int crowSuccess = pfsm->m_crow - pfsm->m_crowNonAcpt;
+ pass_fsm += sizeof(data16) * (crowSuccess + 1); // m_prgirulnMin
+ pass_fsm += sizeof(data16) * (pfsm->m_crulnMatched); // m_prgrulnMatched
+ pass_fsm += sizeof(short) * ((pfsm->m_crow - pfsm->m_crowFinal) * pfsm->m_ccol);
+ pass_fsm += sizeof(data16); // m_dimcrInit, m_cLoop, m_imcrStart
+ pass_fsm += sizeof(int); // m_cmcr
+ pass_fsm += sizeof(void*); // m_prgmcr
+ pass_fsm += sizeof(GrFSMClassRange) * pfsm->m_cmcr;
+ pass_fsm += sizeof(int) * 2; // m_critMinRulePreContext, m_critMaxRulePreContext
+ pass_fsm += sizeof(void*); // m_prgrowStartStates
+ pass_fsm += sizeof(short) * (pfsm->m_critMaxRulePreContext - pfsm->m_critMinRulePreContext + 1);
+ }
+
+ pass_ruleExtras = sizeof(data16) * ppass->m_crul; // m_prgchwRuleSortKeys
+ pass_ruleExtras = sizeof(byte*) * ppass->m_crul; // m_prgcritRulePreModContext
+
+ pass_constraintOffsets += sizeof(data16) * (ppass->m_crul + 1);
+ pass_actionOffsets =+ sizeof(data16) * (ppass->m_crul + 1);
+
+ pass_constraintCode += sizeof(byte) * ppass->m_cbConstraints;
+ pass_actionCode += sizeof(byte) * ppass->m_cbActions;
+
+ pass_general += sizeof(bool) * ppass->m_crul; // m_prgfRuleOkay
+ pass_general += vectorOverhead; // m_vnStack
+ pass_general += sizeof(int) * ppass->m_vnStack.capacity();
+ }
+
+ engst_general += sizeof(EngineState);
+ engst_general += sizeof(void *) * ptman->m_engst.m_vslotblk.capacity();
+ engst_general += sizeof(void *) * ptman->m_engst.m_vprgnSlotVarLenBufs.capacity();
+ engst_general += sizeof(void *) * ptman->m_engst.m_cpass; // m_prgpsstrm
+
+ engst_passState += sizeof(PassState) * ptman->m_engst.m_cpass;
+
+ for (int isstrm = 0; isstrm < ptman->m_engst.m_cpass; isstrm++)
+ {
+ sstrm_count++;
+ GrSlotStream * psstrm = ptman->m_engst.m_prgpsstrm[isstrm];
+ sstrm_general += sizeof(GrSlotStream);
+ sstrm_chunkMapsUsed += psstrm->m_vislotPrevChunkMap.size();
+ sstrm_chunkMapsUsed += psstrm->m_vislotPrevChunkMap.size();
+ sstrm_chunkMapsAlloc += psstrm->m_vislotPrevChunkMap.capacity();
+ sstrm_chunkMapsAlloc += psstrm->m_vislotNextChunkMap.capacity();
+ sstrm_reprocBuf += psstrm->m_vpslotReproc.capacity();
+ sstrm_reprocBuf += sizeof(int) * 2;
+ sstrm_general -= sizeof(int) * 2;
+ }
+
+ slot_general += ptman->m_engst.m_vslotblk.size() * EngineState::kSlotBlockSize
+ * (sizeof(GrSlotState) - sizeof(GrSlotAbstract));
+ slot_abstract += ptman->m_engst.m_vslotblk.size() * EngineState::kSlotBlockSize
+ * sizeof(GrSlotAbstract);
+ int cnExtraPerSlot = ptman->m_engst.m_cUserDefn + (ptman->m_engst.m_cCompPerLig * 2)
+ + ptman->m_engst.m_cFeat;
+ slot_varLenBuf += EngineState::kSlotBlockSize * cnExtraPerSlot * sizeof(u_intslot);
+ for (size_t islotblk = 0; islotblk < ptman->m_engst.m_vslotblk.size(); islotblk++)
+ {
+ for (int islot = 0; islot < EngineState::kSlotBlockSize; islot++)
+ {
+ slot_count++;
+ GrSlotState * pslot = ptman->m_engst.m_vslotblk[islotblk] + islot;
+ slot_assocsUsed += pslot->m_vpslotAssoc.size();
+ slot_assocsAlloc += pslot->m_vpslotAssoc.capacity();
+ slot_attachUsed += pslot->m_vdislotAttLeaves.size();
+ slot_attachAlloc += pslot->m_vdislotAttLeaves.capacity();
+ }
+ }
+
+}
+
+/*----------------------------------------------------------------------------------------------
+ Write out the memory usage onto a stream.
+----------------------------------------------------------------------------------------------*/
+void FontMemoryUsage::prettyPrint(std::ostream & strm)
+{
+ int totalBytes = total();
+
+ strm << "Number of engines: " << eng_count << "\n";
+ strm << "Number of passes: " << pass_count << "\n\n";
+
+ strm << "Number of slot streams: " << sstrm_count << "\n";
+ strm << "Number of slots: " << slot_count << "\n\n";
+
+ int classTableTotal = clstbl_counters + clstbl_offsets + clstbl_glyphList;
+ int glyphTableTotal = glftbl_general + glftbl_compDefns + glftbl_attrTable + glftbl_attrOffsets;
+ int langTableTotal = lngtbl_general + lngtbl_entries + lngtbl_featureSets;
+ int passTotal = pass_general + pass_fsm + pass_ruleExtras + pass_constraintOffsets + pass_constraintCode
+ + pass_actionOffsets + pass_actionCode;
+ int engineTotal = eng_overhead + eng_scalars + eng_strings + eng_pointers + eng_cmap + eng_nameTable
+ + pseudoMap + classTableTotal + glyphTableTotal + langTableTotal + tman_general
+ + passTotal;
+
+ strm << "BYTE COUNT TOTALS\n";
+ strm << "Font: " << font << "\n";
+ strm << "Font cache: " << fontCache << "\n";
+ strm << "Font face: " << fontFace << "\n";
+ strm << "Engine " << engineTotal << "\n";
+ strm << " Overhead: " << eng_overhead << "\n";
+ strm << " Scalars: " << eng_scalars << "\n";
+ strm << " Strings: " << eng_strings << "\n";
+ strm << " Pointers: " << eng_pointers << "\n";
+ strm << " Cmap table: " << eng_cmap << "\n";
+ strm << " Name table: " << eng_nameTable << "\n";
+ strm << " Pseudo map: " << pseudoMap << "\n";
+ strm << " Class table: " << classTableTotal << "\n";
+ strm << " Counters: " << clstbl_counters << "\n";
+ strm << " Offsets: " << clstbl_offsets << "\n";
+ strm << " Glyph list: " << clstbl_glyphList << "\n";
+ strm << " Glyph table: " << glyphTableTotal << "\n";
+ strm << " General: " << glftbl_general << "\n";
+ strm << " Component defns: " << glftbl_compDefns << "\n";
+ strm << " Attr table: " << glftbl_attrTable << "\n";
+ strm << " Attr offsets: " << glftbl_attrOffsets << "\n";
+ strm << " Language table: " << langTableTotal << "\n";
+ strm << " General: " << lngtbl_general << "\n";
+ strm << " Entries: " << lngtbl_entries << "\n";
+ strm << " Feature sets: " << lngtbl_featureSets << "\n";
+ strm << " Table manager: " << tman_general << "\n";
+ strm << " Passes: " << passTotal << "\n";
+ strm << " General: " << pass_general << "\n";
+ strm << " FSM: " << pass_fsm << "\n";
+ strm << " Rule extras: " << pass_ruleExtras << "\n";
+ strm << " Constraint offsets: " << pass_constraintOffsets << "\n\n";
+ strm << " Constraint code: " << pass_constraintCode << "\n";
+ strm << " Action offsets: " << pass_actionOffsets << "\n";
+ strm << " Action code: " << pass_actionCode << "\n\n";
+
+ int slotTotal = slot_general + slot_abstract + slot_varLenBuf + slot_assocsAlloc + slot_attachAlloc;
+ int streamTotal = sstrm_general + sstrm_chunkMapsAlloc + sstrm_reprocBuf + slotTotal;
+ int engineStateTotal = engst_general + engst_passState + streamTotal;
+
+ strm << " Engine State: " << engineStateTotal << "\n";
+ strm << " General: " << engst_general << "\n";
+ strm << " Pass states: " << engst_passState << "\n";
+ strm << " Slot streams: " << streamTotal << "\n";
+ strm << " General: " << sstrm_general << "\n";
+ strm << " Chunk maps: " << sstrm_chunkMapsAlloc << " (" << sstrm_chunkMapsUsed << " used)\n";
+ strm << " Reprocess buffer: " << sstrm_reprocBuf << "\n";
+ strm << " Slots: " << slotTotal << "\n";
+ strm << " General: " << slot_general << "\n";
+ strm << " Abstract: " << slot_abstract << "\n";
+ strm << " Var-length buf: " << slot_varLenBuf << "\n";
+ strm << " Associations: " << slot_assocsAlloc << " (" << slot_assocsUsed << " used)\n";
+ strm << " Attachments: " << slot_attachAlloc << " (" << slot_attachUsed << " used)\n\n";
+
+ strm << "Total bytes used: " << totalBytes << "\n\n";
+
+ strm << "TOTALS PER FONT\n";
+ for (size_t ifont = 0; ifont < vstrFontNames.size(); ifont++)
+ {
+ strm << vstrFontNames[ifont].c_str() << "\n";
+ strm << " Regular: " << vFontTotalsReg[ifont] << "\n";
+ strm << " Bold: " << vFontTotalsBold[ifont] << "\n";
+ strm << " Italic: " << vFontTotalsItalic[ifont] << "\n";
+ strm << " Bold-italic: " << vFontTotalsBI[ifont] << "\n\n";
+ }
+}
+
+
+//:>********************************************************************************************
+//:> Segment
+//:>********************************************************************************************
+
+/*----------------------------------------------------------------------------------------------
+ Initialize the data structure.
+----------------------------------------------------------------------------------------------*/
+void SegmentMemoryUsage::initialize()
+{
+ seg_count = 0;
+ overhead = 0;
+ pointers = 0;
+ scalars = 0;
+ strings = 0;
+ metrics = 0;
+ associations = 0;
+ init = 0;
+ obsolete = 0;
+
+ slot_count = 0;
+ slot_abstract = 0;
+ slot_varLenBuf = 0;
+ slot_scalars = 0;
+ slot_clusterMembers = 0;
+
+ glyphInfo_count = 0;
+ glyphInfo = 0;
+
+ wastedVector = 0;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Add the memory for the segemtn to the SegmentMemoryUsage data structure.
+----------------------------------------------------------------------------------------------*/
+void Segment::calculateMemoryUsage(SegmentMemoryUsage & smu)
+{
+ smu.addSegment(*this);
+}
+
+
+void SegmentMemoryUsage::addSegment(Segment & seg)
+{
+ seg_count++;
+
+ overhead += sizeof(long); // m_cref
+ pointers += sizeof(void*); // m_pgts
+ scalars += sizeof(int); // m_dichwLim
+ scalars += sizeof(int); // m_ichwMin
+ pointers += sizeof(void*); // m_pfont
+ pointers += sizeof(void*); // m_preneng
+ scalars += sizeof(bool); // m_fErroneous
+ pointers += sizeof(void*); // m_pgjus
+ scalars += sizeof(LayoutEnvironment);
+ scalars += sizeof(bool); // m_fWsRtl
+ scalars += sizeof(bool); // m_fParaRtl
+ scalars += sizeof(TrWsHandling);
+ scalars += sizeof(int); // m_nDirDepth
+ init += sizeof(byte*); // m_prgbNextSegDat
+ init += sizeof(int); // m_cbNextSegDat
+ init += sizeof(byte) * seg.m_cbNextSegDat;
+ init += sizeof(byte*); // m_prgInitDat
+ init += sizeof(int); // m_cbInitDat
+ init += sizeof(byte) * seg.m_cbInitDat;
+ init += sizeof(int); // m_dichPreContext
+// obsolete += sizeof(void *); // m_psegPrev
+// obsolete += sizeof(void *); // m_psegNext
+// strings += stringOverhead * 2;
+// strings += sizeof(wchar_t) * seg.m_stuFaceName.length();
+// strings += sizeof(wchar_t) * seg.m_stuBaseFaceName.length();
+// scalars += sizeof(bool); // m_fUseSepBase;
+// scalars += sizeof(float); // m_pixHeight
+// scalars += sizeof(bool); // m_fBold
+// scalars += sizeof(bool); // m_fItalic
+ scalars += sizeof(LineBrk); // m_lbStart
+ scalars += sizeof(LineBrk); // m_lbEnd
+ scalars += sizeof(bool); // m_fStartLine
+ scalars += sizeof(bool); // m_fEndLine
+ scalars += sizeof(SegEnd); // m_est
+ metrics += sizeof(int); // m_mFontEmUnits
+ metrics += sizeof(float) * 17; // was 19, removed m_x/ysDPI
+ associations += sizeof(int); // m_ichwAssocsMin
+ associations += sizeof(int); // m_ichwAssocsLim
+ int dichw = seg.m_ichwAssocsLim - seg.m_ichwAssocsMin;
+ associations += sizeof(int*); // m_prgisloutBefore
+ associations += sizeof(int) * dichw;
+ associations += sizeof(int*); // m_prgisloutAfter
+ associations += sizeof(int) * dichw;
+ associations += sizeof(void*); // m_prgpvisloutAssocs
+ associations += sizeof(void*) * dichw;
+ for (int idichw = 0; idichw < dichw; idichw++)
+ {
+ std::vector<int> * pvisloutAssocs = seg.m_prgpvisloutAssocs[idichw];
+ if (pvisloutAssocs)
+ {
+ associations += vectorOverhead;
+ associations += sizeof(int) * pvisloutAssocs->capacity();
+ wastedVector += sizeof(int) * (pvisloutAssocs->capacity() - pvisloutAssocs->size());
+ }
+ }
+ associations += sizeof(int*); // m_prgisloutLigature
+ associations += sizeof(int) * dichw;
+ associations += sizeof(sdata8*); // m_prgiComponent
+ associations += sizeof(sdata8) * dichw;
+// obsolete += sizeof(void*); // m_psstrm
+ scalars += sizeof(int); // m_cslout
+ slot_count += seg.m_cslout;
+ for (int islout = 0; islout < seg.m_cslout; islout++)
+ {
+ GrSlotOutput * pslout = seg.m_prgslout + islout;
+ slot_abstract += sizeof(gid16) * 2; // m_chwGlyphID, m_chwActual
+ slot_abstract += sizeof(sdata8) * 4; // m_spsl, m_dirc, m_lb, m_nDirLevel
+// slot_abstract += sizeof(float) * 8; // font/glyph metrics
+ slot_abstract += sizeof(short) * 5; // slot attributes - was 21
+ slot_abstract += sizeof(int); // m_mJWidth0;
+ slot_abstract += sizeof(byte); // m_nJWeight0;
+ slot_abstract += sizeof(bool); // m_fInsertBefore
+ slot_abstract += sizeof(sdata8); // m_bIsSpace
+ slot_abstract += sizeof(byte); // m_cnCompPerLig
+ slot_abstract += sizeof(void*); // m_prgnVarLenBuf
+ slot_varLenBuf += pslout->CExtraSpaceSlout() * sizeof(u_intslot);
+ slot_abstract += sizeof(float); // m_xsPositionX, m_ysPositionY
+// slot_abstract += sizeof(bool); // m_fAdvXSet, m_fAdvYSet
+ slot_scalars += sizeof(int) * 2; // m_ichwBefore/AfterAssoc
+ slot_scalars += sizeof(sdata8); // m_cComponents
+ slot_scalars += sizeof(int); // m_isloutClusterBase
+ slot_scalars += sizeof(sdata8); // m_disloutCluster
+ slot_scalars += sizeof(float) * 3; // m_xsClusterXOffset, m_xsClusterAdvance, m_xsAdvanceX
+ slot_scalars += sizeof(int); // m_igbb
+// slot_scalars += sizeof(Rect); // m_rectBB
+ }
+ scalars += sizeof(int); // m_cnUserDefn
+ scalars += sizeof(int); // m_cnCompPerLig
+ scalars += sizeof(int); // m_cnFeat
+ glyphInfo_count += seg.m_cginf;
+ scalars += sizeof(int); // m_cginf;
+ scalars += sizeof(int); // m_isloutGinf0
+ for (int iginf = 0; iginf < seg.m_cginf; iginf++)
+ {
+ ///GlyphInfo * pginf = seg.m_prgginf + iginf;
+ glyphInfo += sizeof(void *); // m_pseg
+ glyphInfo += sizeof(void *); // m_pslout
+ glyphInfo += sizeof(int); // m_islout
+ }
+ init += sizeof(int); // m_cslotRestartBackup
+ init += vectorOverhead;
+ init += sizeof(sdata8) * seg.m_vnSkipOffsets.capacity();
+ wastedVector += sizeof(sdata8) * (seg.m_vnSkipOffsets.capacity() - seg.m_vnSkipOffsets.size());
+ init += sizeof(DirCode); // m_dircPrevStrong
+ init += sizeof(DirCode); // m_dircPrevTerm
+
+ //int grandTotal;
+ //grandTotal = overhead + pointers + scalars + strings + metrics + associations
+ // + init + obsolete + slot_count + slot_abstract + slot_varLenBuf + slot_scalars
+ // + slot_clusterMembers + glyphInfo_count + glyphInfo;
+
+ //int totalPerSeg = grandTotal / seg_count;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Write out the memory usage onto a stream.
+----------------------------------------------------------------------------------------------*/
+void SegmentMemoryUsage::prettyPrint(std::ostream & strm)
+{
+ int totalBytes = overhead + pointers + scalars + strings + metrics + associations
+ + init + obsolete + slot_count + slot_abstract + slot_varLenBuf + slot_scalars
+ + slot_clusterMembers + glyphInfo_count + glyphInfo;
+
+ int slotTotal = slot_abstract + slot_varLenBuf + slot_scalars + slot_clusterMembers;
+
+ strm << "Number of segments: " << seg_count << "\n\n";
+
+ strm << "TOTALS\n";
+ strm << "Overhead: " << overhead << "\n";
+ strm << "Pointers: " << pointers << "\n";
+ strm << "Scalars: " << scalars << "\n";
+ strm << "Strings: " << strings << "\n";
+ strm << "Metrics: " << metrics << "\n";
+ strm << "Associations: " << associations << "\n";
+ strm << "Obsolete: " << obsolete << "\n";
+ strm << "Slot data: " << slotTotal << "\n";
+ strm << " Abstract: " << slot_abstract << "\n";
+ strm << " Var-length buffer: " << slot_varLenBuf << "\n";
+ strm << " Scalars: " << slot_scalars << "\n";
+ strm << " Cluster members: " << slot_clusterMembers << "\n";
+ strm << "Glyph info: " << glyphInfo << "\n\n";
+
+ strm << "Wasted in vectors: " << wastedVector << "\n\n";
+
+ strm << "Total bytes used: " << totalBytes << "\n\n";
+
+ if (seg_count > 0)
+ {
+ strm << "AVERAGES\n";
+ strm << "Overhead: " << overhead/seg_count << "\n";
+ strm << "Pointers: " << pointers/seg_count << "\n";
+ strm << "Scalars: " << scalars/seg_count << "\n";
+ strm << "Strings: " << strings/seg_count << "\n";
+ strm << "Metrics: " << metrics/seg_count << "\n";
+ strm << "Associations: " << associations/seg_count << "\n";
+ strm << "Obsolete: " << obsolete/seg_count << "\n";
+ strm << "Slot data: " << slotTotal/seg_count << "\n";
+ strm << " Abstract: " << slot_abstract/seg_count << "\n";
+ strm << " Var-length buffer: " << slot_varLenBuf/seg_count << "\n";
+ strm << " Scalars: " << slot_scalars/seg_count << "\n";
+ strm << " Cluster members: " << slot_clusterMembers/seg_count << "\n";
+ strm << "Glyph info: " << glyphInfo/seg_count << "\n\n";
+
+ strm << "Avg. bytes per segment: " << totalBytes / seg_count << "\n\n";
+
+ strm << "Avg. # of slots per segment: " << slot_count / seg_count << "\n\n";
+ }
+}
+
+} //namespace gr
+
diff --git a/Build/source/libs/graphite-engine/src/segment/Segment.cpp b/Build/source/libs/graphite-engine/src/segment/Segment.cpp
index 319baef85b5..69e5349bca3 100644
--- a/Build/source/libs/graphite-engine/src/segment/Segment.cpp
+++ b/Build/source/libs/graphite-engine/src/segment/Segment.cpp
@@ -75,20 +75,20 @@ Segment::Segment() :
m_cbNextSegDat(0),
m_prgInitDat(NULL),
m_cbInitDat(0),
- m_fUseSepBase(0),
+// m_fUseSepBase(0),
//m_psegAltEndLine(NULL),
m_prgisloutBefore(NULL),
m_prgisloutAfter(NULL),
- m_prgvisloutAssocs(NULL),
+ m_prgpvisloutAssocs(NULL),
m_prgisloutLigature(NULL),
m_prgiComponent(NULL),
- m_psstrm(NULL),
+// m_psstrm(NULL),
m_cslout(0),
m_prgslout(NULL),
m_prgnSlotVarLenBuf(NULL),
- m_cnUserDefn(0),
+// m_cnUserDefn(0),
m_cnCompPerLig(0),
- m_cnFeat(0),
+// m_cnFeat(0),
m_cginf(0),
m_prgginf(NULL)
{
@@ -96,8 +96,8 @@ Segment::Segment() :
g_csegTotal++;
- m_stuFaceName.erase();
- m_stuBaseFaceName.erase();
+// m_stuFaceName.erase();
+// m_stuBaseFaceName.erase();
m_vnSkipOffsets.clear();
}
@@ -247,12 +247,12 @@ void Segment::Initialize(ITextSource * pgts, int ichwMin, int ichwLim,
m_dxsVisibleWidth = -1;
m_dxsTotalWidth = -1;
- m_psstrm = NULL;
+// m_psstrm = NULL;
m_prgslout = NULL;
m_prgnSlotVarLenBuf = NULL;
m_prgisloutBefore = NULL;
m_prgisloutAfter = NULL;
- m_prgvisloutAssocs = NULL;
+ m_prgpvisloutAssocs = NULL;
m_prgisloutLigature = NULL;
m_prgiComponent = NULL;
@@ -261,12 +261,12 @@ void Segment::Initialize(ITextSource * pgts, int ichwMin, int ichwLim,
//m_psegAltEndLine = NULL;
- m_stuFaceName.erase();
- m_stuBaseFaceName.erase();
- m_fUseSepBase = false;
+// m_stuFaceName.erase();
+// m_stuBaseFaceName.erase();
+// m_fUseSepBase = false;
- m_psegPrev = NULL; // obsolete
- m_psegNext = NULL;
+// m_psegPrev = NULL; // obsolete
+// m_psegNext = NULL;
//InitializePlatform();
}
@@ -311,7 +311,12 @@ void Segment::DestroyContents()
delete[] m_prgnSlotVarLenBuf;
delete[] m_prgisloutBefore;
delete[] m_prgisloutAfter;
- delete[] m_prgvisloutAssocs;
+ for (int ichw = 0; ichw < m_ichwAssocsLim - m_ichwAssocsMin; ichw++)
+ {
+ if (m_prgpvisloutAssocs && m_prgpvisloutAssocs[ichw])
+ delete m_prgpvisloutAssocs[ichw];
+ }
+ delete[] m_prgpvisloutAssocs;
delete[] m_prgisloutLigature;
delete[] m_prgiComponent;
delete[] m_prgbNextSegDat;
@@ -446,14 +451,14 @@ Segment::Segment(Segment & seg)
m_cbNextSegDat = seg.m_cbNextSegDat;
m_prgbNextSegDat = new byte[m_cbNextSegDat];
std::copy(seg.m_prgbNextSegDat, seg.m_prgbNextSegDat + m_cbNextSegDat, m_prgbNextSegDat);
- m_psegPrev = seg.m_psegPrev;
- m_psegNext = seg.m_psegNext;
- m_stuFaceName = seg.m_stuFaceName;
- m_stuBaseFaceName = seg.m_stuBaseFaceName;
- m_fUseSepBase = seg.m_fUseSepBase;
- m_pixHeight = seg.m_pixHeight;
- m_fBold = seg.m_fBold;
- m_fItalic = seg.m_fItalic;
+// m_psegPrev = seg.m_psegPrev;
+// m_psegNext = seg.m_psegNext;
+// m_stuFaceName = seg.m_stuFaceName;
+// m_stuBaseFaceName = seg.m_stuBaseFaceName;
+// m_fUseSepBase = seg.m_fUseSepBase;
+// m_pixHeight = seg.m_pixHeight;
+// m_fBold = seg.m_fBold;
+// m_fItalic = seg.m_fItalic;
m_lbStart = seg.m_lbStart;
m_lbEnd = seg.m_lbEnd;
m_fStartLine = seg.m_fStartLine;
@@ -463,8 +468,8 @@ Segment::Segment(Segment & seg)
m_dysFontAscent = seg.m_dysFontAscent;
m_dysFontDescent = seg.m_dysFontDescent;
m_xysEmSquare = seg.m_xysEmSquare;
- m_xsDPI = seg.m_xsDPI;
- m_ysDPI = seg.m_ysDPI;
+// m_xsDPI = seg.m_xsDPI;
+// m_ysDPI = seg.m_ysDPI;
m_dxsStretch = seg.m_dxsStretch;
m_dxsWidth = seg.m_dxsWidth;
m_dysHeight = seg.m_dysHeight;
@@ -488,16 +493,22 @@ Segment::Segment(Segment & seg)
std::copy(seg.m_prgisloutBefore, seg.m_prgisloutBefore + dichw, m_prgisloutBefore);
m_prgisloutAfter = new int[dichw];
std::copy(seg.m_prgisloutAfter, seg.m_prgisloutAfter + dichw, m_prgisloutAfter);
- m_prgvisloutAssocs = new std::vector<int>[dichw];
- std::copy(seg.m_prgvisloutAssocs, seg.m_prgvisloutAssocs + dichw,
- m_prgvisloutAssocs);
+ m_prgpvisloutAssocs = new std::vector<int> * [dichw];
+ for (int ivislout = 0; ivislout < dichw; ivislout++)
+ {
+ std::vector<int> * pvislout = seg.m_prgpvisloutAssocs[ivislout];
+ if (pvislout)
+ {
+ std::vector<int> * pvisloutNew = new std::vector<int>;
+ m_prgpvisloutAssocs[ivislout] = pvisloutNew;
+ *pvisloutNew = *pvislout; // copy the vector
+ }
+ }
m_prgisloutLigature = new int[dichw];
std::copy(seg.m_prgisloutLigature, seg.m_prgisloutLigature + dichw, m_prgisloutLigature);
- m_prgiComponent = new int[dichw];
+ m_prgiComponent = new sdata8[dichw];
std::copy(seg.m_prgiComponent, seg.m_prgiComponent + dichw, m_prgiComponent);
- // m_psstrm
-
m_cslout = seg.m_cslout;
int cnExtraPerSlot = (m_cslout > 0) ? seg.m_prgslout[0].CExtraSpaceSlout() : 0;
m_prgnSlotVarLenBuf = new u_intslot[m_cslout * cnExtraPerSlot];
@@ -511,9 +522,9 @@ Segment::Segment(Segment & seg)
cnExtraPerSlot);
}
- m_cnUserDefn = seg.m_cnUserDefn;
+// m_cnUserDefn = seg.m_cnUserDefn;
m_cnCompPerLig = seg.m_cnCompPerLig;
- m_cnFeat = seg.m_cnFeat;
+// m_cnFeat = seg.m_cnFeat;
m_cslotRestartBackup = seg.m_cslotRestartBackup;
std::copy(seg.m_prgnSlotVarLenBuf, seg.m_prgnSlotVarLenBuf +
(m_cslout * cnExtraPerSlot), m_prgnSlotVarLenBuf);
@@ -921,14 +932,19 @@ std::pair<GlyphIterator, GlyphIterator> Segment::glyphs()
----------------------------------------------------------------------------------------------*/
std::pair<GlyphSetIterator, GlyphSetIterator> Segment::charToGlyphs(toffset ich)
{
- std::vector<int> * pvislout = UnderlyingToLogicalAssocs(ich);
+ std::vector<int> vislout = UnderlyingToLogicalAssocs(ich);
- // UnderlyingToLogicalAssocs can return NULL for edge cases
- if (pvislout == NULL)
+ if (vislout.size() == 0)
return std::make_pair(GlyphSetIterator(), GlyphSetIterator());
else
- return std::make_pair(GlyphSetIterator(*this, 0, *pvislout),
- GlyphSetIterator(*this, pvislout->size(), *pvislout));
+ {
+ // Note that BOTH instances of GlyphSetIterator must use the same underlying vector,
+ // so that comparisons make sense.
+ RcVector * qvislout = new RcVector(vislout);
+ return std::make_pair(
+ GlyphSetIterator(*this, 0, qvislout),
+ GlyphSetIterator(*this, vislout.size(), qvislout));
+ }
}
/*----------------------------------------------------------------------------------------------
@@ -1107,7 +1123,7 @@ LineBrk Segment::getBreakWeight(int ich, bool fBreakBefore)
return klbClipBreak;
GrSlotOutput * psloutFirst = m_prgslout + isloutFirst;
bool fNotFirst = false;
- if (psloutFirst->HasComponents()
+ if ((psloutFirst->NumberOfComponents() > 0)
&& psloutFirst->UnderlyingComponent(0) != ich)
{
// Not the first component of a ligature.
@@ -1124,7 +1140,7 @@ LineBrk Segment::getBreakWeight(int ich, bool fBreakBefore)
return klbClipBreak;
GrSlotOutput * psloutLast = m_prgslout + isloutLast;
bool fNotLast = false;
- if (psloutLast->HasComponents()
+ if ((psloutLast->NumberOfComponents() > 0)
&& psloutLast->UnderlyingComponent(psloutLast->NumberOfComponents() - 1) != ich)
{
// Not the last component of a ligature.
@@ -1285,7 +1301,7 @@ int Segment::findNextBreakPoint(int ichStart,
else
iginfMin = iginfMid;
}
- Assert(iginfLim < m_cginf);
+ Assert(iginfLim <= m_cginf);
if (iginfLim >= m_cginf) iginfLim = m_cginf - 1;
ichFit = PhysicalSurfaceToUnderlying(iginfLim, false);
}
@@ -1534,11 +1550,11 @@ void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman,
m_mFontEmUnits = EngineImpl()->GetFontEmUnits();
pfont->getFontMetrics(&m_dysFontAscent, &m_dysFontDescent, &m_xysEmSquare);
- m_xsDPI = (float)pfont->getDPIx();
- m_ysDPI = (float)pfont->getDPIy();
+// m_xsDPI = (float)pfont->getDPIx();
+// m_ysDPI = (float)pfont->getDPIy();
// Note that storing both of these values is redundant; they should be the same.
- Assert(m_xysEmSquare == m_pixHeight);
+// Assert(m_xysEmSquare == m_pixHeight);
m_twsh = twsh;
m_fParaRtl = fParaRtl;
@@ -1560,24 +1576,24 @@ void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman,
m_prgisloutAfter = new int[cchwInThisSeg];
- m_prgvisloutAssocs = new std::vector<int>[cchwInThisSeg];
+ m_prgpvisloutAssocs = new std::vector<int> * [cchwInThisSeg];
m_prgisloutLigature = new int[cchwInThisSeg];
- m_prgiComponent = new int[cchwInThisSeg];
+ m_prgiComponent = new sdata8[cchwInThisSeg];
int cslot = 0;
- m_psstrm = psstrmFinal; // TODO: make a local variable
- if (m_psstrm)
- cslot = m_psstrm->FinalSegLim();
+ //m_psstrm = psstrmFinal; // TODO: make a local variable
+ if (psstrmFinal)
+ cslot = psstrmFinal->FinalSegLim();
else
Assert(fEmpty);
float xsMin = 0;
int islot;
- int islotMin = (m_psstrm) ? m_psstrm->IndexOffset() : 0;
+ int islotMin = (psstrmFinal) ? psstrmFinal->IndexOffset() : 0;
for (islot = islotMin; islot < cslot; islot++)
- xsMin = min(xsMin, m_psstrm->SlotAt(islot)->XPosition());
+ xsMin = min(xsMin, psstrmFinal->SlotAt(islot)->XPosition());
// For right-to-left segments, the draw origin is at the left side of the visible
// portion of the text. So if necessary, scoot everything left so that the invisible
@@ -1587,7 +1603,7 @@ void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman,
float dxsInvisible = (m_fEndLine) ? m_dxsTotalWidth - m_dxsVisibleWidth : 0;
for (islot = islotMin; ((m_nDirDepth % 2) && (islot < cslot)); islot++)
{
- GrSlotState * pslot = m_psstrm->SlotAt(islot);
+ GrSlotState * pslot = psstrmFinal->SlotAt(islot);
// int islout = islot - islotMin;
if (pslot->GlyphID() == chwLB)
continue; // skip over linebreak markers
@@ -1606,38 +1622,50 @@ void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman,
{
m_prgisloutBefore[ichw] = kPosInfinity;
m_prgisloutAfter[ichw] = kNegInfinity;
- m_prgvisloutAssocs[ichw].clear();
+ m_prgpvisloutAssocs[ichw] = new std::vector<int>;
m_prgisloutLigature[ichw] = kNegInfinity;
m_prgiComponent[ichw] = 0;
}
m_cslout = csloutSurface;
- m_cnUserDefn = ptman->NumUserDefn();
+ if (ptman->NumUserDefn() > 0 && ptman->NumCompPerLig() > 0)
+ {
+ int x; x = 3;
+ }
+
+// m_cnUserDefn = ptman->NumUserDefn();
m_cnCompPerLig = ptman->NumCompPerLig();
- m_cnFeat = ptman->NumFeat();
+// m_cnFeat = ptman->NumFeat();
// Normal buffers, plus underlying indices of ligature components, plus
// map from used components to defined components.
- int cnExtraPerSlot = m_cnUserDefn + (m_cnCompPerLig * 2) + m_cnFeat + (m_cnCompPerLig * 2);
+// int cnExtraPerSlot = m_cnUserDefn + (m_cnCompPerLig * 2) + m_cnFeat + (m_cnCompPerLig * 2);
+
+ // We don't need to store the user-defined slot attributes or the features in the segment itself.
+ // What we need is: (1) component.ref attr settings, (2) slot-attribute indices,
+ // (3) underlying indicates of ligature components, and (4) map from used components
+ // to defined components
+ int cnExtraPerSlot = m_cnCompPerLig * 4;
m_prgslout = new GrSlotOutput[m_cslout];
m_prgnSlotVarLenBuf = new u_intslot[m_cslout * cnExtraPerSlot];
m_isloutVisLim = 0;
- if (m_psstrm)
+ if (psstrmFinal)
{
for (islot = islotMin; islot < psstrmFinal->FinalSegLim(); ++islot)
{
- int isloutAdj = islot - islotMin;
+ int isloutRel = islot - islotMin;
GrSlotState * pslot = psstrmFinal->SlotAt(islot);
- pslot->SetPosPassIndex(isloutAdj, false);
+ pslot->SetPosPassIndex(isloutRel, false);
pslot->EnsureCacheForOutput(ptman);
- GrSlotOutput * pslout = OutputSlot(isloutAdj);
- pslout->SetBufferPtr(m_prgnSlotVarLenBuf + (isloutAdj * cnExtraPerSlot));
- pslout->CopyFrom(pslot);
+ GrSlotOutput * pslout = OutputSlot(isloutRel);
+ pslout->SetBufferPtr(m_prgnSlotVarLenBuf + (isloutRel * cnExtraPerSlot));
+ pslout->InitializeOutputFrom(pslot);
pslout->SetBeforeAssoc(pslot->BeforeAssoc());
pslout->SetAfterAssoc(pslot->AfterAssoc());
if (pslot->HasComponents())
- pslot->SetComponentRefsFor(pslout); // also sets it for pslout, since they share the buffer
+ pslot->SetComponentRefsFor(pslout);
+ Assert(pslot->HasComponents() == (pslout->NumberOfComponents() > 0));
//if (pslot->HasClusterMembers())
//{
//Assert(pslot->HasClusterMembers() || pslot->ClusterRootOffset() == 0);
@@ -1659,7 +1687,7 @@ void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman,
int isloutBaseIndex = pslot->Base(psstrmFinal)->PosPassIndex();
if (!pslot->IsBase())
{
- OutputSlot(isloutBaseIndex)->AddClusterMember(pslot->PosPassIndex());
+ OutputSlot(isloutBaseIndex)->AddClusterMember(isloutBaseIndex, pslot->PosPassIndex());
OutputSlot(isloutAdj)->SetClusterBase(isloutBaseIndex);
}
else if (pslot->HasClusterMembers() && pslot->IsBase())
@@ -1680,7 +1708,7 @@ void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman,
// Final output for draw routines.
- SetUpGlyphInfo(ptman, chwLB, nDirDepth, islotMin, cslot);
+ SetUpGlyphInfo(ptman, psstrmFinal, chwLB, nDirDepth, islotMin, cslot);
//SetUpOutputArraysPlatform(ptman, chwLB, nDirDepth, islotMin, cslot);
@@ -1689,8 +1717,8 @@ void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman,
/*----------------------------------------------------------------------------------------------
Set up the data structures that represent the actual rendered glyphs for the new segment.
----------------------------------------------------------------------------------------------*/
-void Segment::SetUpGlyphInfo(GrTableManager * ptman, gid16 chwLB, int nDirDepth,
- int islotMin, int cslot)
+void Segment::SetUpGlyphInfo(GrTableManager * ptman, GrSlotStream * psstrmFinal,
+ gid16 chwLB, int nDirDepth, int islotMin, int cslot)
{
//int paraDirLevel = (ptman->State()->ParaRightToLeft()) ? 1 : 0;
@@ -1699,7 +1727,7 @@ void Segment::SetUpGlyphInfo(GrTableManager * ptman, gid16 chwLB, int nDirDepth,
int islot;
for (islot = islotMin; islot < cslot; islot++)
{
- if (m_psstrm->SlotAt(islot)->GlyphID() != chwLB)
+ if (psstrmFinal->SlotAt(islot)->GlyphID() != chwLB)
{
m_cginf++;
}
@@ -1718,7 +1746,7 @@ void Segment::SetUpGlyphInfo(GrTableManager * ptman, gid16 chwLB, int nDirDepth,
int iginf = 0;
for (int islot = islotMin; islot < cslot; islot++)
{
- GrSlotState * pslot = m_psstrm->SlotAt(islot);
+ GrSlotState * pslot = psstrmFinal->SlotAt(islot);
if (pslot->GlyphID() == chwLB)
{
@@ -1737,32 +1765,37 @@ void Segment::SetUpGlyphInfo(GrTableManager * ptman, gid16 chwLB, int nDirDepth,
// Fill in stuff in the output slot that is needed by the GlyphInfo object.
pslout->m_xsAdvanceX = pslot->GlyphMetricLogUnits(ptman, kgmetAdvWidth);
- pslout->m_ysAdvanceY = pslot->GlyphMetricLogUnits(ptman, kgmetAdvHeight);
- pslout->m_rectBB.top
- = pslot->YPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbTop);
- pslout->m_rectBB.bottom
- = pslot->YPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbBottom);
- pslout->m_rectBB.left
- = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbLeft);
- if (pslot->IsSpace(ptman))
- pslout->m_rectBB.right
- = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetAdvWidth);
- else
- pslout->m_rectBB.right
- = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbRight);
+ //pslout->m_ysAdvanceY = pslot->GlyphMetricLogUnits(ptman, kgmetAdvHeight);
+ //pslout->m_rectBB.top
+ // = pslot->YPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbTop);
+ //pslout->m_rectBB.bottom
+ // = pslot->YPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbBottom);
+ //pslout->m_rectBB.left
+ // = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbLeft);
+ //if (pslot->IsSpace(ptman))
+ // pslout->m_rectBB.right
+ // = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetAdvWidth);
+ //else
+ // pslout->m_rectBB.right
+ // = pslot->XPosition() + pslot->GlyphMetricLogUnits(ptman, kgmetBbRight);
iginf++;
}
if (cslot - islotMin == 0)
m_isloutGinf0 = 0;
+ if (m_isloutGinf0 == -1)
+ {
+ Assert(m_cginf == 0);
+ m_isloutGinf0 = ((OutputSlot(0)->IsInitialLineBreak()) ? 1 : 0);
+ }
Assert(m_isloutGinf0 == 0 || m_isloutGinf0 == 1);
}
/*
// OLD VERSION
-void Segment::SetUpGlyphInfo(GrTableManager * ptman, gid16 chwLB, int nDirDepth,
+void Segment::SetUpGlyphInfo(GrTableManager * ptman, GrSlotStream * psstrmFinal, gid16 chwLB, int nDirDepth,
int islotMin, int cslot)
{
int paraDirLevel = (ptman->State()->ParaRightToLeft()) ? 1 : 0;
@@ -1771,7 +1804,7 @@ void Segment::SetUpGlyphInfo(GrTableManager * ptman, gid16 chwLB, int nDirDepth,
int islot;
for (islot = islotMin; islot < cslot; islot++)
{
- if (m_psstrm->SlotAt(islot)->GlyphID() != chwLB)
+ if (psstrmFinal->SlotAt(islot)->GlyphID() != chwLB)
m_cginf++;
}
@@ -1788,7 +1821,7 @@ void Segment::SetUpGlyphInfo(GrTableManager * ptman, gid16 chwLB, int nDirDepth,
m_isloutGinf0 = -1;
for (islot = islotMin; islot < cslot; islot++)
{
- GrSlotState * pslot = m_psstrm->SlotAt(islot);
+ GrSlotState * pslot = psstrmFinal->SlotAt(islot);
int islout = islot - islotMin;
if (pslot->GlyphID() == chwLB)
@@ -2030,6 +2063,30 @@ void Segment::AdjustAfterArrayFromNextSeg()
#endif // -------------------------- END OF OBSOLETE CODE ----------------------------------
+
+/*----------------------------------------------------------------------------------------------
+ Generate a list of all the glyphs that are attached to the base with the given index.
+ Note that we want to generate glyph indices, not slot indices.
+
+ @param disloutCluster - indicates how far on either side of the base to look.
+----------------------------------------------------------------------------------------------*/
+void Segment::ClusterMembersForGlyph(int isloutBase, int disloutCluster,
+ std::vector<int> & visloutRet)
+{
+ for (int islout = max(0, isloutBase - disloutCluster);
+ islout < min(m_cslout, isloutBase + disloutCluster + 1);
+ islout++)
+ {
+ if (islout == isloutBase)
+ continue; // don't include the base itself
+ GrSlotOutput * pslout = m_prgslout + islout;
+ if (pslout->ClusterBase() == isloutBase)
+ {
+ visloutRet.push_back(islout);
+ }
+ }
+}
+
/*----------------------------------------------------------------------------------------------
Record an underlying-to-surface association mapping, based on the fact that there is
a corresponding surface-to-underlying association in the streams.
@@ -2062,7 +2119,7 @@ void Segment::RecordSurfaceAssoc(int ichwUnder, int islotSurface, int nDir)
min(m_prgisloutAfter[ ichwUnder - m_ichwAssocsMin], islotSurface);
}
- m_prgvisloutAssocs[ichwUnder - m_ichwAssocsMin].push_back(islotSurface);
+ m_prgpvisloutAssocs[ichwUnder - m_ichwAssocsMin]->push_back(islotSurface);
}
/*----------------------------------------------------------------------------------------------
@@ -2083,7 +2140,8 @@ void Segment::RecordLigature(int ichwUnder, int islotSurface, int iComponent)
Assert(m_prgisloutLigature[ichwUnder - m_ichwAssocsMin] == kNegInfinity);
m_prgisloutLigature[ichwUnder - m_ichwAssocsMin] = islotSurface;
- m_prgiComponent[ ichwUnder - m_ichwAssocsMin] = iComponent;
+ Assert(iComponent < kMaxComponentsPerGlyph);
+ m_prgiComponent[ ichwUnder - m_ichwAssocsMin] = sdata8(iComponent);
}
/*----------------------------------------------------------------------------------------------
@@ -2141,12 +2199,12 @@ void Segment::EnsureSpaceAtLineBoundaries(int ichwUnder)
m_prgisloutAfter + cchwPreAdd);
delete[] prgisloutTmp;
- std::vector<int> * pvisloutTmp = m_prgvisloutAssocs;
- m_prgvisloutAssocs = new std::vector<int>[cchwNewLim - cchwNewMin];
- std::swap_ranges(m_prgvisloutAssocs + cchwPreAdd,
- m_prgvisloutAssocs + cchwPreAdd +
- (m_ichwAssocsLim - m_ichwAssocsMin), pvisloutTmp);
- delete[] pvisloutTmp;
+ std::vector<int> ** ppvisloutTmp = m_prgpvisloutAssocs;
+ m_prgpvisloutAssocs = new std::vector<int> * [cchwNewLim - cchwNewMin];
+ std::swap_ranges(m_prgpvisloutAssocs + cchwPreAdd,
+ m_prgpvisloutAssocs + cchwPreAdd +
+ (m_ichwAssocsLim - m_ichwAssocsMin), ppvisloutTmp);
+ delete[] ppvisloutTmp;
prgisloutTmp = m_prgisloutLigature;
m_prgisloutLigature = new int[cchwNewLim - cchwNewMin];
@@ -2154,11 +2212,11 @@ void Segment::EnsureSpaceAtLineBoundaries(int ichwUnder)
m_prgisloutLigature + cchwPreAdd);
delete[] prgisloutTmp;
- prgisloutTmp = m_prgiComponent;
- m_prgiComponent = new int[cchwNewLim - cchwNewMin];
- std::copy(prgisloutTmp, prgisloutTmp + (m_ichwAssocsLim - m_ichwAssocsMin),
+ sdata8 * prgiCompTmp = m_prgiComponent;
+ m_prgiComponent = new sdata8[cchwNewLim - cchwNewMin];
+ std::copy(prgiCompTmp, prgiCompTmp + (m_ichwAssocsLim - m_ichwAssocsMin),
m_prgiComponent + cchwPreAdd);
- delete[] prgisloutTmp;
+ delete[] prgiCompTmp;
// Initialize new slots.
int i;
@@ -2166,7 +2224,7 @@ void Segment::EnsureSpaceAtLineBoundaries(int ichwUnder)
{
m_prgisloutBefore[i] = kPosInfinity;
m_prgisloutAfter[i] = kNegInfinity;
- m_prgvisloutAssocs[i].clear();
+ m_prgpvisloutAssocs[i] = new std::vector<int>;
m_prgisloutLigature[i] = kNegInfinity;
m_prgiComponent[i] = 0;
}
@@ -2176,7 +2234,7 @@ void Segment::EnsureSpaceAtLineBoundaries(int ichwUnder)
{
m_prgisloutBefore[i] = kPosInfinity;
m_prgisloutAfter[i] = kNegInfinity;
- m_prgvisloutAssocs[i].clear();
+ m_prgpvisloutAssocs[i] = new std::vector<int>;
m_prgisloutLigature[i] = kNegInfinity;
m_prgiComponent[i] = 0;
}
@@ -2212,11 +2270,11 @@ void Segment::SetFont(Font * pfont)
{
m_pfont = pfont->copyThis();
- m_fBold = pfont->bold();
- m_fItalic = pfont->italic();
+// m_fBold = pfont->bold();
+// m_fItalic = pfont->italic();
// Note that we store the character height (which does not include the internal leading),
// not the actual font height, ie, ascent + descent. This is what is used in the LOGFONT.
- pfont->getFontMetrics(NULL, NULL, &m_pixHeight);
+ pfont->getFontMetrics(NULL, NULL, &m_xysEmSquare); // m_xysEmSquare = m_pixHeight
}
/*----------------------------------------------------------------------------------------------
@@ -2308,7 +2366,7 @@ int Segment::LogicalSurfaceToUnderlying(int islout, float xsOffset, float ysClic
// If the slot has components, see if the offset falls within one of them.
- if (pslout->HasComponents())
+ if (pslout->NumberOfComponents() > 0)
{
GrEngine * pgreng = EngineImpl();
if (!pgreng)
@@ -2388,6 +2446,9 @@ LNotLigature:
// diCharAdj--;
}
+ if (dichw == kNegInfinity || dichw == kPosInfinity)
+ return dichw;
+
// This should be true because of the way the associations are set up:
Assert(GrCharStream::AtUnicodeCharBoundary(m_pgts, m_ichwMin + dichw)); // + diCharAdj));
@@ -2516,6 +2577,7 @@ int Segment::LogicalToPhysicalSurface(int islout)
return the physical surface locations of all the associated surface glyphs.
OBSOLETE
----------------------------------------------------------------------------------------------*/
+#if 0
void Segment::UnderlyingToPhysicalAssocs(int ichw, std::vector<int> & viginf)
{
int ichwSegOffset = ichw - m_ichwMin;
@@ -2539,29 +2601,48 @@ void Segment::UnderlyingToPhysicalAssocs(int ichw, std::vector<int> & viginf)
}
}
}
+#endif
/*----------------------------------------------------------------------------------------------
Given an underlying character position (relative to the beginning of the string),
return a pointer to the vector containing the logical surface locations of
all the associated surface glyphs.
- WARNING: this method returns a pointer to the actual data, not a copy of it.
- Do not modify the returned vector!
+ Returns an empty vector (not something containing infinities) if the character is
+ "invisible."
----------------------------------------------------------------------------------------------*/
-std::vector<int> * Segment::UnderlyingToLogicalAssocs(int ichw)
+std::vector<int> Segment::UnderlyingToLogicalAssocs(int ichw)
{
+ std::vector<int> vnEmpty;
+ vnEmpty.clear();
+ Assert(vnEmpty.size() == 0);
+
int ichwSegOffset = ichw - m_ichwMin;
if (ichwSegOffset < m_ichwAssocsMin)
- return NULL; // probably rendered in previous segment
+ return vnEmpty; // probably rendered in previous segment
else if (ichwSegOffset >= m_ichwAssocsLim)
- return NULL; // probably rendered in following segment
+ return vnEmpty; // probably rendered in following segment
+ else if (m_prgpvisloutAssocs[ichwSegOffset - m_ichwAssocsMin] == NULL)
+ {
+ // Create a vector using the before and after values.
+ std::vector<int> visloutRet;
+ int isloutBefore = m_prgisloutBefore[ichwSegOffset - m_ichwAssocsMin];
+ int isloutAfter = m_prgisloutAfter[ichwSegOffset - m_ichwAssocsMin];
+ if (isloutBefore != kPosInfinity && isloutBefore != kNegInfinity)
+ visloutRet.push_back(isloutBefore);
+ if (isloutAfter != kPosInfinity && isloutAfter != kNegInfinity && isloutBefore != isloutAfter)
+ {
+ visloutRet.push_back(isloutAfter);
+ }
+ return visloutRet;
+ }
else
{
- std::vector<int> * pvisloutRet = &(m_prgvisloutAssocs[ichwSegOffset - m_ichwAssocsMin]);
- return pvisloutRet;
+ std::vector<int> * pvisloutRet = m_prgpvisloutAssocs[ichwSegOffset - m_ichwAssocsMin];
+ return *pvisloutRet;
}
}
@@ -2573,15 +2654,12 @@ std::vector<int> * Segment::UnderlyingToLogicalAssocs(int ichw)
int Segment::UnderlyingToLogicalInThisSeg(int ichw)
{
int isloutTest = kNegInfinity;
- std::vector<int> * pvislout = UnderlyingToLogicalAssocs(ichw);
- if (pvislout)
+ std::vector<int> vislout = UnderlyingToLogicalAssocs(ichw);
+ for (size_t iislout = 0; iislout < vislout.size(); iislout++)
{
- for (size_t iislout = 0; iislout < pvislout->size(); iislout++)
- {
- isloutTest = (*pvislout)[iislout];
- if (isloutTest != kNegInfinity && isloutTest != kPosInfinity)
- return isloutTest;
- }
+ isloutTest = vislout[iislout];
+ if (isloutTest != kNegInfinity && isloutTest != kPosInfinity)
+ return isloutTest;
}
return isloutTest;
}
@@ -2591,20 +2669,26 @@ int Segment::UnderlyingToLogicalInThisSeg(int ichw)
----------------------------------------------------------------------------------------------*/
bool Segment::SameSurfaceGlyphs(int ichw1, int ichw2)
{
- std::vector<int> * pvislout1 = UnderlyingToLogicalAssocs(ichw1);
- std::vector<int> * pvislout2 = UnderlyingToLogicalAssocs(ichw2);
-
- if (pvislout1 == NULL || pvislout1 == NULL)
- return false;
+ std::vector<int> vislout1 = UnderlyingToLogicalAssocs(ichw1);
+ std::vector<int> vislout2 = UnderlyingToLogicalAssocs(ichw2);
- if (pvislout1->size() != pvislout2->size())
- return false;
- for (size_t islout = 0; islout < pvislout1->size(); islout++)
+ bool fRet = true;
+ if (vislout1.size() == 0 || vislout2.size() == 0)
+ fRet = false;
+ else if (vislout1.size() != vislout2.size())
+ fRet = false;
+ else
{
- if ((*pvislout1)[islout] != (*pvislout2)[islout])
- return false;
+ for (size_t islout = 0; islout < vislout1.size(); islout++)
+ {
+ if (vislout1[islout] != vislout2[islout])
+ {
+ fRet = false;
+ break;
+ }
+ }
}
- return true;
+ return fRet;
}
/*----------------------------------------------------------------------------------------------
@@ -2767,9 +2851,9 @@ GrResult Segment::getUniscribeClusters(
// insertion is not allowed.
for (ich = 0; ich < m_dichwLim; ich++)
{
- std::vector<int> * pvislout = UnderlyingToLogicalAssocs(ich + m_ichwMin);
+ std::vector<int> vislout = UnderlyingToLogicalAssocs(ich + m_ichwMin);
- if (!pvislout || pvislout->size() == 0)
+ if (vislout.size() == 0)
{
// No glyphs represent this character. Merge it with the previous
// character.
@@ -2779,9 +2863,9 @@ GrResult Segment::getUniscribeClusters(
}
size_t iislout;
- for (iislout = 0; iislout < pvislout->size(); iislout++)
+ for (iislout = 0; iislout < vislout.size(); iislout++)
{
- int islout = (*pvislout)[iislout];
+ int islout = vislout[iislout];
if (!m_prgslout[islout].InsertBefore())
{
// This glyph does not allow insertion before it; make its character part
@@ -2823,6 +2907,10 @@ GrResult Segment::getUniscribeClusters(
for (ich = 0; ich < m_dichwLim - 1; ich++)
{
Assert(visloutBefore[ich] <= visloutAfter[ich]);
+ Assert(visloutBefore[ich] != kPosInfinity);
+ Assert(visloutBefore[ich] != kNegInfinity);
+ Assert(visloutAfter[ich] != kPosInfinity);
+ Assert(visloutAfter[ich] != kNegInfinity);
const int b1 = visloutBefore[ich];
const int a1 = visloutAfter[ich];
const int b2 = visloutBefore[ich + 1];
@@ -3174,10 +3262,11 @@ int Segment::GlyphHit(float xsClick, float ysClick)
return 0;
}
- // Find all BB that OVERLAP the click point (BbLeft < XClick < BbRight).
+ // Find all BB that OVERLAP the click point (bb.left < XClick < bb.right).
for (iginf = iginfHit; iginf >= 0; iginf--)
{
- if (m_prgginf[iginf].bb().left <= xsClick && xsClick <= m_prgginf[iginf].bb().right)
+ Rect rectBB = m_prgginf[iginf].bb();
+ if (rectBB.left <= xsClick && xsClick <= rectBB.right)
{
viginfNear.push_back(iginf);
}
@@ -3194,11 +3283,36 @@ int Segment::GlyphHit(float xsClick, float ysClick)
}
}
- // Find all BB for which the click is within their advance width.
+ if (viginfNear.size() > 2 && viginfHit.size() == 0)
+ {
+ // No hit along y-axis; find the closest thing.
+ float dy = float(10000000.0);
+ for (int iiginf2 = 0; iiginf2 < (int)viginfNear.size(); iiginf2++)
+ {
+ Rect rectBB = m_prgginf[viginfNear[iiginf2]].bb();
+ if (fabsf(rectBB.top - ysClick) < dy)
+ {
+ dy = fabsf(rectBB.top - ysClick);
+ viginfHit.clear();
+ viginfHit.push_back(viginfNear[iiginf2]);
+ }
+ if (fabsf(rectBB.bottom - ysClick) < dy)
+ {
+ dy = fabsf(rectBB.bottom - ysClick);
+ viginfHit.clear();
+ viginfHit.push_back(viginfNear[iiginf2]);
+ }
+ }
+ }
+
+ // Find all BB for which the click is within their advance width, if any.
for (iiginf = 0; iiginf < (int)viginfHit.size(); iiginf++)
{
- Rect rectBB = m_prgginf[viginfHit[iiginf]].bb();
- if (rectBB.left <= xsClick && xsClick <= rectBB.right)
+ //Rect rectBB = m_prgginf[viginfHit[iiginf]].bb(); -- ?? this tests the bounding box again :-/
+ //if (rectBB.left <= xsClick && xsClick <= rectBB.right)
+ gr::GlyphInfo * pginf = m_prgginf + viginfHit[iiginf];
+ if (pginf->advanceWidth() == 0 // advance width is irrelevant
+ || (pginf->origin() < xsClick && xsClick <= pginf->origin() + pginf->advanceWidth()))
{
viginfInside.push_back(viginfHit[iiginf]);
}
@@ -3253,7 +3367,8 @@ int Segment::GlyphHit(float xsClick, float ysClick)
/*----------------------------------------------------------------------------------------------
Select the bounding box we will use for a mouse hit.
- Select the BB with the left-most (LTR) or right-most (RTL) edge.
+ First select any glyph with a significantly smaller bounding box.
+ Then, select the BB with the left-most (LTR) or right-most (RTL) edge.
If more than one BB has same edge of interest, select the one that is closest to the
the baseline.
If that is a tie, select the one with the lowest islout.
@@ -3272,6 +3387,27 @@ int Segment::SelectBb(std::vector<int> & viginf, bool fRTL)
if (viginf.size() == 1)
return viginf[0];
+ // Find a glyph that has a signficantly smaller bounding box.
+ // The idea is that it is going to be harder to hit than the bigger glyph.
+ float smallestArea = float(1000000000.0);
+ float largestArea = 0.0;
+ size_t iiginfSmallest;
+ size_t iiginf;
+ for (iiginf = 0; iiginf < viginf.size(); iiginf++)
+ {
+ gr::GlyphInfo * pginf = m_prgginf + viginf[iiginf];
+ Rect rectBB = pginf->bb();
+ float thisArea = (rectBB.right - rectBB.left) * (rectBB.top - rectBB.bottom);
+ if (smallestArea > thisArea)
+ {
+ smallestArea = thisArea;
+ iiginfSmallest = iiginf;
+ }
+ largestArea = max(largestArea, thisArea);
+ }
+ if (smallestArea * 2.0 < largestArea)
+ return viginf[iiginfSmallest];
+
// Find appropriate x coor of leading edge.
float xsLeading;
if (!fRTL)
@@ -3279,27 +3415,28 @@ int Segment::SelectBb(std::vector<int> & viginf, bool fRTL)
else
xsLeading = m_prgginf[viginf[0]].bb().right;
- size_t iiginf;
for (iiginf = 1; iiginf < viginf.size(); iiginf++)
{
+ Rect rectBB = m_prgginf[viginf[iiginf]].bb();
if (!fRTL)
- xsLeading = min(xsLeading, m_prgginf[viginf[iiginf]].bb().left);
+ xsLeading = min(xsLeading, rectBB.left);
else
- xsLeading = max(xsLeading, m_prgginf[viginf[iiginf]].bb().right);
+ xsLeading = max(xsLeading, rectBB.right);
}
// Find BBs with the leading edge.
std::vector<int> viginfSameEdge;
for (iiginf = 0; iiginf < viginf.size(); iiginf++)
{
+ Rect rectBB = m_prgginf[viginf[iiginf]].bb();
if (!fRTL)
{
- if (m_prgginf[viginf[iiginf]].bb().left == xsLeading)
+ if (rectBB.left == xsLeading)
viginfSameEdge.push_back(viginf[iiginf]);
}
else
{
- if (m_prgginf[viginf[iiginf]].bb().right == xsLeading)
+ if (rectBB.right == xsLeading)
viginfSameEdge.push_back(viginf[iiginf]);
}
}
diff --git a/Build/source/libs/graphite-engine/src/segment/SegmentAux.cpp b/Build/source/libs/graphite-engine/src/segment/SegmentAux.cpp
index 00dce43df65..9191e8724d5 100644
--- a/Build/source/libs/graphite-engine/src/segment/SegmentAux.cpp
+++ b/Build/source/libs/graphite-engine/src/segment/SegmentAux.cpp
@@ -77,11 +77,12 @@ float GlyphInfo::attachedClusterAdvance() const throw()
std::pair<gr::GlyphSetIterator, gr::GlyphSetIterator> GlyphInfo::attachedClusterGlyphs() const
{
+ std::vector<int> visloutClusterMembers;
+ m_pslout->ClusterMembers(m_pseg, m_islout, visloutClusterMembers);
+ RcVector * qvislout = new RcVector(visloutClusterMembers);
return std::make_pair(
- GlyphSetIterator(*m_pseg, 0,
- m_pslout->m_visloutClusterMembers),
- GlyphSetIterator(*m_pseg, m_pslout->m_visloutClusterMembers.size(),
- m_pslout->m_visloutClusterMembers));
+ GlyphSetIterator(*m_pseg, 0, qvislout),
+ GlyphSetIterator(*m_pseg, visloutClusterMembers.size(), qvislout));
}
size_t GlyphInfo::logicalIndex()
@@ -104,7 +105,8 @@ float GlyphInfo::advanceWidth() // logical units
float GlyphInfo::advanceHeight() // logical units; zero for horizontal fonts
{
- return m_pslout->m_xysAdvY;
+ Font & font = m_pseg->getFont();
+ return m_pslout->GlyphMetricLogUnits(&font, kgmetAdvHeight);
}
float GlyphInfo::yOffset()
@@ -114,7 +116,7 @@ float GlyphInfo::yOffset()
Rect GlyphInfo::bb() // logical units
{
- return m_pslout->m_rectBB;
+ return m_pslout->BoundingBox(m_pseg->getFont());
}
bool GlyphInfo::isSpace()
@@ -221,13 +223,21 @@ bool GlyphInfo::erroneous()
//:> GlyphIterator methods
//:>********************************************************************************************
- // Constructor
+// Constructor
GlyphIterator::GlyphIterator(Segment & seg, size_t iginf)
-: _itr(seg.m_prgginf + iginf)
+: m_pginf(seg.m_prgginf + iginf)
{}
-GlyphIterator::GlyphIterator(const GlyphSetIterator &set_itr)
-: _itr(set_itr->segment().m_prgginf + set_itr->logicalIndex())
+// Copy constructor.
+// Check if the incoming iterator is null, as we cannot dereference
+// it to get the segment, and create a null GlyphIterator.
+// Technically this might better be an assert as converting a null
+// GlyphSetIterator into a null GlyphIterator is pointless and suggests
+// some kind of error.
+GlyphIterator::GlyphIterator(const GlyphSetIterator & sit)
+: m_pginf((sit == GlyphSetIterator())
+ ? 0
+ : sit->segment().m_prgginf + sit->logicalIndex())
{}
/*----------------------------------------------------------------------------------------------
@@ -236,9 +246,10 @@ GlyphIterator::GlyphIterator(const GlyphSetIterator &set_itr)
GlyphSetIterator::reference GlyphSetIterator::operator*() const
{
- assert(_seg_ptr);
+ assert(m_pseg != 0);
+ assert(m_vit != std::vector<int>::const_iterator());
// in the case of a non-contiguous list
- return _seg_ptr->m_prgginf[(*_itr) - _seg_ptr->m_isloutGinf0];
+ return m_pseg->m_prgginf[(*m_vit) - m_pseg->m_isloutGinf0];
}
diff --git a/Build/source/libs/graphite-engine/src/segment/TransductionLog.cpp b/Build/source/libs/graphite-engine/src/segment/TransductionLog.cpp
index 658b2ec1044..29a1be2af12 100644
--- a/Build/source/libs/graphite-engine/src/segment/TransductionLog.cpp
+++ b/Build/source/libs/graphite-engine/src/segment/TransductionLog.cpp
@@ -973,7 +973,8 @@ void Segment::LogUnderlyingToSurface(GrTableManager * ptman, std::ostream & strm
int ichw;
for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++)
{
- cassocs = max(cassocs, m_prgvisloutAssocs[ichw].size());
+ if (m_prgpvisloutAssocs[ichw])
+ cassocs = max(cassocs, m_prgpvisloutAssocs[ichw]->size());
if (m_prgisloutLigature[ichw] != kNegInfinity)
fLigs = true;
}
@@ -1080,7 +1081,7 @@ void Segment::LogUnderlyingToSurface(GrTableManager * ptman, std::ostream & strm
}
strmOut <<"\n";
- for (size_t ix = 1; ix < cassocs - 1; ix++) //(cassocs > 2)
+ for (int ix = 1; ix < signed(cassocs) - 1; ix++) //(cassocs > 2)
{
if (ix == 1)
strmOut << "other ";
@@ -1088,10 +1089,13 @@ void Segment::LogUnderlyingToSurface(GrTableManager * ptman, std::ostream & strm
strmOut << " ";
for (ichw = 0; ichw < (m_ichwAssocsLim - m_ichwAssocsMin); ichw++)
{
- if (m_prgvisloutAssocs[ichw].size() <= ix)
+ std::vector<int> * pvislout = m_prgpvisloutAssocs[ichw];
+ if (pvislout == NULL)
strmOut << " ";
- else if (m_prgvisloutAssocs[ichw][ix] != m_prgisloutAfter[ichw])
- ptman->LogInTable(strmOut, m_prgvisloutAssocs[ichw][ix]);
+ else if (signed(pvislout->size()) <= ix)
+ strmOut << " ";
+ else if ((*pvislout)[ix] != m_prgisloutAfter[ichw])
+ ptman->LogInTable(strmOut, (*pvislout)[ix]);
else
strmOut << " ";
}
@@ -1171,8 +1175,7 @@ void Segment::LogSurfaceToUnderlying(GrTableManager * ptman, std::ostream & strm
else
{
ptman->LogHexInTable(strmOut, psloutTmp->GlyphID());
- if (psloutTmp->HasComponents())
- ccomp = max(ccomp, psloutTmp->NumberOfComponents());
+ ccomp = max(ccomp, psloutTmp->NumberOfComponents());
}
}
strmOut << "\n";
@@ -1464,9 +1467,9 @@ void GrSlotState::SlotAttrsModified(bool * rgfMods, bool fPreJust, int * pccomp,
if (m_nAttachLevel != 0)
rgfMods[kslatAttLevel] = true;
- if (m_lb != kNotYetSet)
+ if (m_lb != kNotYetSet8)
rgfMods[kslatBreak] = true;
- if (m_dirc != kNotYetSet)
+ if (m_dirc != kNotYetSet8)
rgfMods[kslatDir] = true;
if (m_fInsertBefore != true)
rgfMods[kslatInsert] = true;
@@ -1759,14 +1762,14 @@ void GrSlotState::LogSlotAttribute(GrTableManager * ptman,
break;
case kslatBreak:
- if (m_lb != (pslotPrev ? pslotPrev->m_lb : kNotYetSet))
+ if (m_lb != (pslotPrev ? pslotPrev->m_lb : kNotYetSet8))
{
ptman->LogBreakWeightInTable(strmOut, m_lb);
return;
}
break;
case kslatDir:
- if (m_dirc != (pslotPrev ? pslotPrev->m_dirc : kNotYetSet))
+ if (m_dirc != (pslotPrev ? pslotPrev->m_dirc : kNotYetSet8))
{
ptman->LogDirCodeInTable(strmOut, m_dirc);
return;
diff --git a/Build/source/libs/graphite-engine/src/segment/explicit_instantiations.cpp b/Build/source/libs/graphite-engine/src/segment/explicit_instantiations.cpp
deleted file mode 100644
index 0aa2a40dddf..00000000000
--- a/Build/source/libs/graphite-engine/src/segment/explicit_instantiations.cpp
+++ /dev/null
@@ -1,44 +0,0 @@
-/*--------------------------------------------------------------------*//*:Ignore this sentence.
-Copyright (C) 1999, 2001 SIL International. All rights reserved.
-
-Distributable under the terms of either the Common Public License or the
-GNU Lesser General Public License, as specified in the LICENSING.txt file.
-
-File: explicit_instantiation.cpp
-Responsibility: Sharon Correll
-Last reviewed: Not yet.
-
-Description:
- Explicitly instantiate HashMap and Vector types used in the GrEngine module.
--------------------------------------------------------------------------------*//*:End Ignore*/
-
-// Standard includes for the module, gives the types we have to instantiate
-#include "Main.h"
-#pragma hdrstop
-
-// Standard includes for doing explicit instantiation:
-
-//////#include "Vector_i.cpp"
-
-namespace gr
-{
-
-// Types we use:
-template class std::vector<int>;
-// STL port doesn't like this
-//template class std::vector<bool>;
-template class std::vector<GrSlotState *>;
-template class std::vector<GrGlyphSubTable *>;
-template class std::vector<int *>;
-/////template std::vector<std::wstring>; // remove
-template class std::vector<OLECHAR>;
-template class std::vector<byte>;
-template class std::vector<DirCode>;
-
-// VS6.0 doesn't like these:
-//template std::vector<RECT>;
-//template std::vector<Segment::GlyphStrmKey>;
-//template std::vector<Segment::LineSeg>;
-//template std::vector<GrGlyphIndexPair>;
-
-} // namespace gr