diff options
Diffstat (limited to 'Build/source/libs/graphite-engine/src/segment')
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 |