summaryrefslogtreecommitdiff
path: root/Build/source/libs/graphite/src/font/Font.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/graphite/src/font/Font.cpp')
-rw-r--r--Build/source/libs/graphite/src/font/Font.cpp950
1 files changed, 950 insertions, 0 deletions
diff --git a/Build/source/libs/graphite/src/font/Font.cpp b/Build/source/libs/graphite/src/font/Font.cpp
new file mode 100644
index 00000000000..95cf2cefd41
--- /dev/null
+++ b/Build/source/libs/graphite/src/font/Font.cpp
@@ -0,0 +1,950 @@
+/*--------------------------------------------------------------------*//*:Ignore this sentence.
+Copyright (C) 1999 - 2008 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: Font.cpp
+Responsibility: Sharon Correll
+Last reviewed: Not yet.
+
+Description:
+ A font is an object that knows how to read tables from a (platform-specific) font resource.
+----------------------------------------------------------------------------------------------*/
+
+//:>********************************************************************************************
+//:> Include files
+//:>********************************************************************************************
+#include "Main.h"
+#ifdef _MSC_VER
+#pragma hdrstop
+#endif
+// any other headers (not precompiled)
+
+#undef THIS_FILE
+DEFINE_THIS_FILE
+
+//:End Ignore
+
+//:>********************************************************************************************
+//:> Forward declarations
+//:>********************************************************************************************
+
+//:>********************************************************************************************
+//:> Local Constants and static variables
+//:>********************************************************************************************
+
+
+namespace gr
+{
+
+//:>********************************************************************************************
+//:> Font methods
+//:>********************************************************************************************
+
+/*----------------------------------------------------------------------------------------------
+ Constructor.
+----------------------------------------------------------------------------------------------*/
+Font::Font(const Font & fontSrc) : m_pfface(fontSrc.m_pfface), m_fTablesCached(false)
+{
+ if (m_pfface)
+ m_pfface->IncFontCount();
+}
+
+/*----------------------------------------------------------------------------------------------
+ Destructor.
+----------------------------------------------------------------------------------------------*/
+Font::~Font()
+{
+ if (m_pfface)
+ m_pfface->DecFontCount();
+}
+
+/*----------------------------------------------------------------------------------------------
+ Mark the font-cache as to whether it should be deleted when all the font instances go away.
+----------------------------------------------------------------------------------------------*/
+void Font::SetFlushMode(int flush)
+{
+ FontFace::SetFlushMode(flush);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Cache the common tables if necessary.
+----------------------------------------------------------------------------------------------*/
+void Font::EnsureTablesCached()
+{
+ if (m_fTablesCached)
+ return;
+
+ size_t cbBogus;
+ m_pHead = getTable(TtfUtil::TableIdTag(ktiHead), &cbBogus);
+ m_pHmtx = getTable(TtfUtil::TableIdTag(ktiHmtx), &m_cbHmtxSize);
+ m_pGlyf = getTable(TtfUtil::TableIdTag(ktiGlyf), &cbBogus);
+ m_pLoca = getTable(TtfUtil::TableIdTag(ktiLoca), &m_cbLocaSize);
+
+ // getTable can return 0 for the lengths if it is hard to calculate them, but it should
+ // never do that for hmtx or loca.
+ Assert(m_cbHmtxSize > 0);
+ Assert(m_cbLocaSize > 0);
+
+ m_fTablesCached = true;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return the flush mode of the font-cache.
+----------------------------------------------------------------------------------------------*/
+int Font::GetFlushMode()
+{
+ return FontFace::GetFlushMode();
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return the internal object representing the font-face. This is the object that is stored
+ in Graphite's internal cache.
+----------------------------------------------------------------------------------------------*/
+inline FontFace & Font::fontFace(bool fDumbFallback)
+{
+ if (m_pfface == 0)
+ initialiseFontFace(fDumbFallback);
+ return *m_pfface;
+}
+
+void Font::initialiseFontFace(bool fDumbFallback)
+{
+ std::wstring stuFaceName;
+ bool fBold, fItalic;
+
+ UniqueCacheInfo(stuFaceName, fBold, fItalic);
+
+ m_pfface = FontFace::GetFontFace(this, stuFaceName, fBold, fItalic, fDumbFallback);
+
+ Assert(m_pfface != 0);
+
+ m_pfface->IncFontCount();
+
+ FontException fexptn;
+ fexptn.version = -1;
+ fexptn.subVersion = -1;
+ if (m_pfface->BadFont(&fexptn.errorCode)
+ || (!fDumbFallback && m_pfface->DumbFallback(&fexptn.errorCode)))
+ {
+ throw fexptn;
+ }
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return uniquely identifying information that will be used as the key for this font
+ in the font cache. This includes the font face name and the bold and italic flags.
+----------------------------------------------------------------------------------------------*/
+void Font::UniqueCacheInfo(std::wstring & stuFace, bool & fBold, bool & fItalic)
+{
+ size_t cbSize;
+ const byte * pNameTbl = static_cast<const byte *>(getTable(TtfUtil::TableIdTag(ktiName), &cbSize));
+ size_t lOffset, lSize;
+ if (!TtfUtil::Get31EngFamilyInfo(pNameTbl, lOffset, lSize))
+ {
+ // TODO: try to find any name in any arbitrary language.
+ Assert(false);
+ return;
+ }
+ // byte * pvName = (byte *)pNameTbl + lOffset;
+ utf16 rgchwFace[128];
+ const size_t cchw = min(long(lSize / sizeof(utf16)), long((sizeof(rgchwFace) / sizeof(utf16)) - 1));
+ // NOTE: there is a potential alignment problem in the following two lines, which can causes
+ // crashes on architectures that require alignment to word boundaries.
+ const utf16 * pchwNameStart = reinterpret_cast<const utf16 *>(pNameTbl+ lOffset);
+ std::copy(pchwNameStart, pchwNameStart + cchw, rgchwFace);
+ rgchwFace[cchw] = 0; // zero terminate
+ TtfUtil::SwapWString(rgchwFace, cchw);
+ for (size_t ich16 = 0; ich16 < cchw; ich16++) // equivalent to assign, but works in more situations
+ stuFace.push_back(wchar_t(rgchwFace[ich16])); // where where wchar_t is 4 bytes
+
+ const void * pOs2Tbl = getTable(TtfUtil::TableIdTag(ktiOs2), &cbSize);
+ TtfUtil::FontOs2Style(pOs2Tbl, fBold, fItalic);
+ // Do we need to compare the results from the OS2 table with the italic flag in the
+ // head table? (There is no requirement that they be consistent!)
+}
+
+
+/*----------------------------------------------------------------------------------------------
+ A default unhinted implmentation of getGlyphPoint(..)
+----------------------------------------------------------------------------------------------*/
+void Font::getGlyphPoint(gid16 glyphID, unsigned int pointNum, Point & pointReturn)
+{
+ EnsureTablesCached();
+
+ // Default values
+ pointReturn.x = 0;
+ pointReturn.y = 0;
+
+ if (m_pGlyf == 0) return;
+ if (m_pHead == 0) return;
+ if (m_pLoca == 0) return;
+
+ size_t cContours;
+ size_t cPoints;
+
+ const size_t CONTOUR_BUF_SIZE = 16;
+ const size_t POINT_BUF_SIZE = 64;
+ // Fixed-size buffers that will be used in most cases:
+ bool rgfOnCurveFixedBuf[POINT_BUF_SIZE], *rgfOnCurveHeapBuf=0;
+ int rgnEndPtFixedBuf[CONTOUR_BUF_SIZE], *rgnEndPtHeapBuf=0,
+ rgnXFixedBuf[POINT_BUF_SIZE], *rgnXHeapBuf=0,
+ rgnYFixedBuf[POINT_BUF_SIZE], *rgnYHeapBuf=0;
+
+ if (!TtfUtil::GlyfContourCount(glyphID, m_pGlyf, m_pLoca, m_cbLocaSize, m_pHead, cContours))
+ return; // can't figure it out
+
+ int * prgnEndPt = (cContours > CONTOUR_BUF_SIZE) ?
+ rgnEndPtHeapBuf = new int[cContours] :
+ rgnEndPtFixedBuf;
+
+ if (!TtfUtil::GlyfContourEndPoints(glyphID, m_pGlyf, m_pLoca, m_cbLocaSize, m_pHead,
+ prgnEndPt, cContours))
+ {
+ return; // should have been caught above
+ }
+ cPoints = prgnEndPt[cContours - 1] + 1;
+
+ bool* prgfOnCurve = (cPoints > POINT_BUF_SIZE) ? rgfOnCurveHeapBuf= new bool[cPoints] : rgfOnCurveFixedBuf;
+ int * prgnX = (cPoints > POINT_BUF_SIZE) ? rgnXHeapBuf= new int[cPoints] : rgnXFixedBuf;
+ int * prgnY = (cPoints > POINT_BUF_SIZE) ? rgnYHeapBuf= new int[cPoints] : rgnYFixedBuf;
+
+ if (TtfUtil::GlyfPoints(glyphID, m_pGlyf, m_pLoca, m_cbLocaSize, m_pHead, 0, 0,
+ prgnX, prgnY, prgfOnCurve, cPoints))
+ {
+ float nPixEmSquare;
+ getFontMetrics(0, 0, &nPixEmSquare);
+
+ const float nDesignUnitsPerPixel = float(TtfUtil::DesignUnits(m_pHead)) / nPixEmSquare;
+ pointReturn.x = prgnX[pointNum] / nDesignUnitsPerPixel;
+ pointReturn.y = prgnY[pointNum] / nDesignUnitsPerPixel;
+ }
+
+ delete[] rgnEndPtHeapBuf;
+ delete[] rgfOnCurveHeapBuf;
+ delete[] rgnXHeapBuf;
+ delete[] rgnYHeapBuf;
+}
+
+
+/*----------------------------------------------------------------------------------------------
+ A default unhinted implmentation of getGlyphMetrics(..)
+----------------------------------------------------------------------------------------------*/
+void Font::getGlyphMetrics(gid16 glyphID, gr::Rect & boundingBox, gr::Point & advances)
+{
+ EnsureTablesCached();
+
+ // Setup default return values in case of failiure.
+ boundingBox.left = 0;
+ boundingBox.right = 0;
+ boundingBox.bottom = 0;
+ boundingBox.top = 0;
+ advances.x = 0;
+ advances.y = 0;
+
+ if (m_pHead == 0) return;
+
+ // Calculate the number of design units per pixel.
+ float pixelEmSquare;
+ getFontMetrics(0, 0, &pixelEmSquare);
+ const float pixelsPerDesignUnit =
+ pixelEmSquare / float(TtfUtil::DesignUnits(m_pHead));
+
+ // getTable can return 0 for the lengths if it is hard to calculate them, but it should
+ // never do that for hmtx or loca.
+ Assert(m_cbHmtxSize > 0);
+
+ // Use the Hmtx and Head tables to find the glyph advances.
+ int lsb;
+ unsigned int advance = 0;
+ if (TtfUtil::HorMetrics(glyphID, m_pHmtx, m_cbHmtxSize, m_pHead,
+ lsb, advance))
+ {
+ advances.x = (advance * pixelsPerDesignUnit);
+ advances.y = 0.0f;
+ }
+
+ if (m_pGlyf == 0) return;
+ if (m_pLoca == 0) return;
+ Assert(m_cbLocaSize > 0);
+
+ // Fetch the glyph bounding box. GlyphBox may return false for a whitespace glyph.
+ // Note that using GlyfBox here allows attachment points (ie, points lying outside
+ // the glyph's outline) to affect the bounding box, which might not be what we want.
+ int xMin, xMax, yMin, yMax;
+ if (TtfUtil::GlyfBox(glyphID, m_pGlyf, m_pLoca, m_cbLocaSize, m_pHead,
+ xMin, yMin, xMax, yMax))
+ {
+ boundingBox.left = (xMin * pixelsPerDesignUnit);
+ boundingBox.bottom = (yMin * pixelsPerDesignUnit);
+ boundingBox.right = (xMax * pixelsPerDesignUnit);
+ boundingBox.top = (yMax * pixelsPerDesignUnit);
+ }
+}
+
+
+/*----------------------------------------------------------------------------------------------
+ Return a pair of iterators over a sequence of features defined for the font.
+----------------------------------------------------------------------------------------------*/
+std::pair<FeatureIterator, FeatureIterator> Font::getFeatures()
+{
+ std::pair<FeatureIterator, FeatureIterator> pairRet;
+ pairRet.first = BeginFeature();
+ pairRet.second = EndFeature();
+ return pairRet;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Returns an iterator indicating the feature with the given ID. If no such feature,
+ returns the end iterator.
+----------------------------------------------------------------------------------------------*/
+FeatureIterator Font::featureWithID(featid id)
+{
+ FeatureIterator fit = BeginFeature();
+ FeatureIterator fitEnd = EndFeature();
+ for ( ; fit != fitEnd ; ++fit)
+ {
+ if (*fit == id)
+ return fit;
+ }
+ return fitEnd; // invalid
+}
+
+/*----------------------------------------------------------------------------------------------
+ Returns the UI label for the indicated feature. Return false if there is no label for the
+ language, or it is empty.
+----------------------------------------------------------------------------------------------*/
+bool Font::getFeatureLabel(FeatureIterator fit, lgid nLanguage, utf16 * label)
+{
+ return GetFeatureLabel(fit.m_ifeat, nLanguage, label);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Returns an iterator pointing at the default value for the feature.
+----------------------------------------------------------------------------------------------*/
+FeatureSettingIterator Font::getDefaultFeatureValue(FeatureIterator fit)
+{
+ size_t ifset = GetFeatureDefault(fit.m_ifeat);
+ FeatureSettingIterator fsit = fit.BeginSetting();
+ fsit += ifset;
+ return fsit;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Returns a pair of iterators spanning the defined settings for the feature.
+----------------------------------------------------------------------------------------------*/
+std::pair<FeatureSettingIterator, FeatureSettingIterator>
+ Font::getFeatureSettings(FeatureIterator fit)
+{
+ std::pair<FeatureSettingIterator, FeatureSettingIterator> pairRet;
+ pairRet.first = fit.BeginSetting();
+ pairRet.second = fit.EndSetting();
+ return pairRet;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Returns the UI label for the indicated feature. Return false if there is no label for the
+ language, or it is empty.
+----------------------------------------------------------------------------------------------*/
+bool Font::getFeatureSettingLabel(FeatureSettingIterator fsit, lgid nLanguage, utf16 * label)
+{
+ //FeatureIterator * pfit = static_cast<FeatureIterator *>(fsit.m_pfit);
+ return GetFeatureSettingLabel(fsit.m_fit.m_ifeat, fsit.m_ifset, nLanguage, label);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Private methods for feature and language access.
+----------------------------------------------------------------------------------------------*/
+size_t Font::NumberOfFeatures()
+{
+ try {
+ return fontFace().NumberOfFeatures();
+ }
+ catch (...) { return 0; }
+}
+featid Font::FeatureID(size_t ifeat)
+{
+ try {
+ return fontFace().FeatureID(ifeat);
+ }
+ catch (...) { return 0; }
+}
+size_t Font::FeatureWithID(featid id)
+{
+ try {
+ return fontFace().FeatureWithID(id);
+ }
+ catch (...) { return 0; }
+}
+bool Font::GetFeatureLabel(size_t ifeat, lgid language, utf16 * label)
+{
+ try {
+ return fontFace().GetFeatureLabel(ifeat, language, label);
+ }
+ catch (...)
+ {
+ *label = 0;
+ return false;
+ }
+}
+int Font::GetFeatureDefault(size_t ifeat) // index of default setting
+{
+ try {
+ return fontFace().GetFeatureDefault(ifeat);
+ }
+ catch (...) { return 0; }
+}
+size_t Font::NumberOfSettings(size_t ifeat)
+{
+ try {
+ return fontFace().NumberOfSettings(ifeat);
+ }
+ catch (...) { return 0; }
+}
+int Font::GetFeatureSettingValue(size_t ifeat, size_t ifset)
+{
+ try {
+ return fontFace().GetFeatureSettingValue(ifeat, ifset);
+ }
+ catch (...) { return 0; }
+}
+bool Font::GetFeatureSettingLabel(size_t ifeat, size_t ifset, lgid language, utf16 * label)
+{
+ try {
+ return fontFace().GetFeatureSettingLabel(ifeat, ifset, language, label);
+ }
+ catch (...)
+ {
+ *label = 0;
+ return false;
+ }
+}
+size_t Font::NumberOfFeatLangs()
+{
+ try {
+ return fontFace().NumberOfFeatLangs();
+ }
+ catch (...) { return 0; }
+}
+short Font::FeatLabelLang(size_t ilang)
+{
+ try {
+ return fontFace().FeatLabelLang(ilang);
+ }
+ catch (...) { return 0; }
+}
+size_t Font::NumberOfLanguages()
+{
+ try {
+ return fontFace().NumberOfLanguages();
+ }
+ catch (...) { return 0; }
+}
+isocode Font::LanguageCode(size_t ilang)
+{
+ try {
+ return fontFace().LanguageCode(ilang);
+ }
+ catch (...)
+ {
+ isocode ret;
+ std::fill_n(ret.rgch, sizeof(ret.rgch), '\0');
+ return ret;
+ }
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return a pair of iterators over a sequence of feature-label languages for this font.
+----------------------------------------------------------------------------------------------*/
+std::pair<FeatLabelLangIterator, FeatLabelLangIterator> Font::getFeatureLabelLanguages()
+{
+ std::pair<FeatLabelLangIterator, FeatLabelLangIterator> pairRet;
+ pairRet.first = BeginFeatLang();
+ pairRet.second = EndFeatLang();
+ return pairRet;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return a pair of iterators over a sequence of languages defined for the font, that is,
+ those that have features specified for them.
+----------------------------------------------------------------------------------------------*/
+std::pair<LanguageIterator, LanguageIterator> Font::getSupportedLanguages()
+{
+ std::pair<LanguageIterator, LanguageIterator> pairRet;
+ pairRet.first = BeginLanguage();
+ pairRet.second = EndLanguage();
+ return pairRet;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return a bitmap indicating which directions are supported by the font.
+----------------------------------------------------------------------------------------------*/
+ScriptDirCode Font::getSupportedScriptDirections() const throw()
+{
+ try {
+ Font * pfontThis = const_cast<Font *>(this);
+ FontFace & fface = pfontThis->fontFace();
+ return fface.ScriptDirection();
+ }
+ catch (...) {
+ return kfsdcHorizLtr;
+ }
+}
+
+/*----------------------------------------------------------------------------------------------
+ For segment creation.
+----------------------------------------------------------------------------------------------*/
+void Font::RenderLineFillSegment(Segment * pseg, ITextSource * pts, LayoutEnvironment & layout,
+ toffset ichStart, toffset ichStop, float xsMaxWidth, bool fBacktracking)
+{
+ fontFace(layout.dumbFallback()).RenderLineFillSegment(pseg, this, pts, layout,
+ ichStart, ichStop, xsMaxWidth, fBacktracking);
+}
+
+void Font::RenderRangeSegment(Segment * pseg, ITextSource * pts, LayoutEnvironment & layout,
+ toffset ichStart, toffset ichStop)
+{
+ fontFace(layout.dumbFallback()).RenderRangeSegment(pseg, this, pts, layout, ichStart, ichStop);
+}
+
+void Font::RenderJustifiedSegment(Segment * pseg, ITextSource * pts,
+ LayoutEnvironment & layout, toffset ichStart, toffset ichStop,
+ float xsCurrentWidth, float xsDesiredWidth)
+{
+ fontFace(layout.dumbFallback()).RenderJustifiedSegment(pseg, this, pts, layout,
+ ichStart, ichStop, xsCurrentWidth, xsDesiredWidth);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Feature iterators.
+----------------------------------------------------------------------------------------------*/
+FeatureIterator Font::BeginFeature()
+{
+ FeatureIterator fit(this, 0, NumberOfFeatures());
+ return fit;
+}
+
+FeatureIterator Font::EndFeature()
+{
+ int cfeat = NumberOfFeatures();
+ FeatureIterator fit (this, cfeat, cfeat);
+ return fit;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Feature-label language iterators.
+----------------------------------------------------------------------------------------------*/
+FeatLabelLangIterator Font::BeginFeatLang()
+{
+ FeatLabelLangIterator lgit(this, 0, NumberOfFeatLangs());
+ return lgit;
+}
+
+FeatLabelLangIterator Font::EndFeatLang()
+{
+ int clang = NumberOfFeatLangs();
+ FeatLabelLangIterator lgit(this, clang, clang);
+ return lgit;
+}
+
+
+/*----------------------------------------------------------------------------------------------
+ Language iterators.
+----------------------------------------------------------------------------------------------*/
+LanguageIterator Font::BeginLanguage()
+{
+ LanguageIterator lgit(this, 0, NumberOfLanguages());
+ return lgit;
+}
+
+LanguageIterator Font::EndLanguage()
+{
+ int clang = NumberOfLanguages();
+ LanguageIterator lgit(this, clang, clang);
+ return lgit;
+}
+
+
+/*----------------------------------------------------------------------------------------------
+ Debugging.
+----------------------------------------------------------------------------------------------*/
+//bool Font::DbgCheckFontCache()
+//{
+// return FontFace::DbgCheckFontCache();
+//}
+
+
+//:>********************************************************************************************
+//:> FeatureIterator methods
+//:>********************************************************************************************
+
+//FeatureIterator::FeatureIterator(FeatureIterator & fitToCopy)
+//{
+// m_pfont = fitToCopy.m_pfont;
+// m_ifeat = fitToCopy.m_ifeat;
+// m_cfeat = fitToCopy.m_cfeat;
+//}
+
+/*----------------------------------------------------------------------------------------------
+ Dereference the iterator, returning a feature ID.
+----------------------------------------------------------------------------------------------*/
+featid FeatureIterator::operator*()
+{
+ if (m_ifeat >= m_cfeat)
+ {
+ Assert(false);
+ return (unsigned int)kInvalid;
+ }
+
+ return m_pfont->FeatureID(m_ifeat);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Increment the iterator.
+----------------------------------------------------------------------------------------------*/
+FeatureIterator FeatureIterator::operator++()
+{
+ if (m_ifeat >= m_cfeat)
+ {
+ // Can't increment.
+ Assert(false);
+ }
+ else
+ m_ifeat++;
+
+ return *this;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Increment the iterator by the given value.
+----------------------------------------------------------------------------------------------*/
+FeatureIterator FeatureIterator::operator+=(int n)
+{
+ if (m_ifeat + n >= m_cfeat)
+ {
+ // Can't increment.
+ Assert(false);
+ m_ifeat = m_cfeat;
+ }
+ else if (m_ifeat + n < 0)
+ {
+ // Can't decrement.
+ Assert(false);
+ m_ifeat = 0;
+ }
+ else
+ m_ifeat += m_cfeat;
+
+ return *this;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Test whether the two iterators are equal.
+----------------------------------------------------------------------------------------------*/
+bool FeatureIterator::operator==(FeatureIterator & fit)
+{
+ return (fit.m_ifeat == m_ifeat && fit.m_pfont == m_pfont);
+}
+
+bool FeatureIterator::operator!=(FeatureIterator & fit)
+{
+ return (fit.m_ifeat != m_ifeat || fit.m_pfont != m_pfont);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return the number of items represented by the range of the two iterators.
+----------------------------------------------------------------------------------------------*/
+int FeatureIterator::operator-(FeatureIterator & fit)
+{
+ if (m_pfont != fit.m_pfont)
+ {
+ throw;
+ }
+ return (m_ifeat - fit.m_ifeat);
+}
+
+
+/*----------------------------------------------------------------------------------------------
+ Iterators.
+----------------------------------------------------------------------------------------------*/
+FeatureSettingIterator FeatureIterator::BeginSetting()
+{
+ int cfset = m_pfont->NumberOfSettings(m_ifeat);
+ FeatureSettingIterator fsit(*this, 0, cfset);
+ return fsit;
+}
+
+FeatureSettingIterator FeatureIterator::EndSetting()
+{
+ int cfset = m_pfont->NumberOfSettings(m_ifeat);
+ FeatureSettingIterator fsit(*this, cfset, cfset);
+ return fsit;
+}
+
+
+//:>********************************************************************************************
+//:> FeatureSettingIterator methods
+//:>********************************************************************************************
+
+/*----------------------------------------------------------------------------------------------
+ Dereference the iterator, returning a feature value.
+----------------------------------------------------------------------------------------------*/
+int FeatureSettingIterator::operator*()
+{
+ if (m_ifset >= m_cfset)
+ {
+ Assert(false);
+ return kInvalid;
+ }
+
+ return m_fit.m_pfont->GetFeatureSettingValue(m_fit.m_ifeat, m_ifset);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Increment the iterator.
+----------------------------------------------------------------------------------------------*/
+FeatureSettingIterator FeatureSettingIterator::operator++()
+{
+ if (m_ifset >= m_cfset)
+ {
+ // Can't increment.
+ Assert(false);
+ }
+ else
+ m_ifset++;
+
+ return *this;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Increment the iterator by the given value.
+----------------------------------------------------------------------------------------------*/
+FeatureSettingIterator FeatureSettingIterator::operator+=(int n)
+{
+ if (m_ifset + n >= m_cfset)
+ {
+ // Can't increment.
+ Assert(false);
+ m_ifset = m_cfset;
+ }
+ if (m_ifset + n < 0)
+ {
+ // Can't decrement.
+ Assert(false);
+ m_ifset = 0;
+ }
+ else
+ m_ifset += n;
+
+ return *this;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Test whether the two iterators are equal.
+----------------------------------------------------------------------------------------------*/
+bool FeatureSettingIterator::operator==(FeatureSettingIterator & fsit)
+{
+ //FeatureIterator * pfit = static_cast<FeatureIterator *>(m_pfit);
+ //FeatureIterator * pfitOther = static_cast<FeatureIterator *>(fsit.m_pfit);
+ //return (m_ifset == fsit.m_ifset && pfit == pfitOther);
+ return (m_ifset == fsit.m_ifset && m_fit == fsit.m_fit);
+}
+
+bool FeatureSettingIterator::operator!=(FeatureSettingIterator & fsit)
+{
+ //FeatureIterator * pfit = static_cast<FeatureIterator *>(m_pfit);
+ //FeatureIterator * pfitOther = static_cast<FeatureIterator *>(fsit.m_pfit);
+ //return (m_ifset != fsit.m_ifset || pfit != pfitOther);
+
+ return (m_ifset != fsit.m_ifset || m_fit != fsit.m_fit);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return the number of items represented by the range of the two iterators.
+----------------------------------------------------------------------------------------------*/
+int FeatureSettingIterator::operator-(FeatureSettingIterator fsit)
+{
+ //FeatureIterator * pfit = static_cast<FeatureIterator *>(m_pfit);
+ //FeatureIterator * pfitOther = static_cast<FeatureIterator *>(fsit.m_pfit);
+ //if (pfit != pfitOther)
+
+ if (m_fit != fsit.m_fit)
+ {
+ throw;
+ }
+ return (m_ifset - fsit.m_ifset);
+}
+
+//:>********************************************************************************************
+//:> FeatLabelLangIterator methods
+//:>********************************************************************************************
+
+/*----------------------------------------------------------------------------------------------
+ Dereference the iterator, returning a language LCID.
+----------------------------------------------------------------------------------------------*/
+data16 FeatLabelLangIterator::operator*()
+{
+ if (m_ilang >= m_clang)
+ {
+ Assert(false);
+ return 0;
+ }
+
+ return m_pfont->FeatLabelLang(m_ilang);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Increment the iterator.
+----------------------------------------------------------------------------------------------*/
+FeatLabelLangIterator FeatLabelLangIterator::operator++()
+{
+ if (m_ilang >= m_clang)
+ {
+ // Can't increment.
+ Assert(false);
+ }
+ else
+ m_ilang++;
+
+ return *this;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Increment the iterator by the given value.
+----------------------------------------------------------------------------------------------*/
+FeatLabelLangIterator FeatLabelLangIterator::operator+=(int n)
+{
+ if (m_ilang + n >= m_clang)
+ {
+ // Can't increment.
+ Assert(false);
+ m_ilang = m_clang;
+ }
+ else if (m_ilang + n < 0)
+ {
+ // Can't decrement.
+ Assert(false);
+ m_ilang = 0;
+ }
+ else
+ m_ilang += m_clang;
+
+ return *this;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Test whether the two iterators are equal.
+----------------------------------------------------------------------------------------------*/
+bool FeatLabelLangIterator::operator==(FeatLabelLangIterator & fllit)
+{
+ return (fllit.m_ilang == m_ilang && fllit.m_pfont == m_pfont);
+}
+
+bool FeatLabelLangIterator::operator!=(FeatLabelLangIterator & fllit)
+{
+ return (fllit.m_ilang != m_ilang || fllit.m_pfont != m_pfont);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return the number of items represented by the range of the two iterators.
+----------------------------------------------------------------------------------------------*/
+int FeatLabelLangIterator::operator-(FeatLabelLangIterator & fllit)
+{
+ if (m_pfont != fllit.m_pfont)
+ {
+ throw;
+ }
+ return (m_ilang - fllit.m_ilang);
+}
+
+
+//:>********************************************************************************************
+//:> LanguageIterator methods
+//:>********************************************************************************************
+
+/*----------------------------------------------------------------------------------------------
+ Dereference the iterator, returning a language code.
+----------------------------------------------------------------------------------------------*/
+isocode LanguageIterator::operator*()
+{
+ if (m_ilang >= m_clang)
+ {
+ Assert(false);
+ isocode codeRet;
+ codeRet.rgch[0] = '?'; codeRet.rgch[1] = '?';
+ codeRet.rgch[2] = '?'; codeRet.rgch[3] = 0;
+ return codeRet;
+ }
+
+ return m_pfont->LanguageCode(m_ilang);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Increment the iterator.
+----------------------------------------------------------------------------------------------*/
+LanguageIterator LanguageIterator::operator++()
+{
+ if (m_ilang >= m_clang)
+ {
+ // Can't increment.
+ Assert(false);
+ }
+ else
+ m_ilang++;
+
+ return *this;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Increment the iterator by the given value.
+----------------------------------------------------------------------------------------------*/
+LanguageIterator LanguageIterator::operator+=(int n)
+{
+ if (m_ilang + n >= m_clang)
+ {
+ // Can't increment.
+ Assert(false);
+ m_ilang = m_clang;
+ }
+ else if (m_ilang + n < 0)
+ {
+ // Can't decrement.
+ Assert(false);
+ m_ilang = 0;
+ }
+ else
+ m_ilang += m_clang;
+
+ return *this;
+}
+
+/*----------------------------------------------------------------------------------------------
+ Test whether the two iterators are equal.
+----------------------------------------------------------------------------------------------*/
+bool LanguageIterator::operator==(LanguageIterator & lgit)
+{
+ return (lgit.m_ilang == m_ilang && lgit.m_pfont == m_pfont);
+}
+
+bool LanguageIterator::operator!=(LanguageIterator & lgit)
+{
+ return (lgit.m_ilang != m_ilang || lgit.m_pfont != m_pfont);
+}
+
+/*----------------------------------------------------------------------------------------------
+ Return the number of items represented by the range of the two iterators.
+----------------------------------------------------------------------------------------------*/
+int LanguageIterator::operator-(LanguageIterator & lgit)
+{
+ if (m_pfont != lgit.m_pfont)
+ {
+ throw;
+ }
+ return (m_ilang - lgit.m_ilang);
+}
+
+
+} // namespace gr
+
+