[ooo-build-commit] patches/dev300

René Engelhard rene at kemper.freedesktop.org
Tue Jun 30 08:04:49 PDT 2009


 patches/dev300/apply                        |    2 
 patches/dev300/cws-graphite01-20081226.diff | 5531 ----------------------
 patches/dev300/cws-graphite01-20090630.diff | 6952 ++++++++++++++++++++++++++++
 3 files changed, 6953 insertions(+), 5532 deletions(-)

New commits:
commit e59b9a1640810a35a85ced856a7591584fb19de2
Author: Rene Engelhard <rene at debian.org>
Date:   Tue Jun 30 17:03:50 2009 +0200

    update graphite patch
    
    * patches/dev300/cws-graphite01-20081226.diff: move ..
    * patches/dev300/cws-graphite01-20090630.diff:  .. here and add new extract
    * patches/dev300/apply: adapt

diff --git a/patches/dev300/apply b/patches/dev300/apply
index 1a78a33..b2a3add 100644
--- a/patches/dev300/apply
+++ b/patches/dev300/apply
@@ -161,7 +161,7 @@ ooo-build-resources-sc-sc-hrc.diff, kohei
 ooo-build-resources-svx-dialogs-hrc.diff, kohei
 
 [ GraphiteSupport ]
-cws-graphite01-20081226.diff, i#69129
+cws-graphite01-20090630.diff, i#69129
 
 [ HelpContent ]
 helpcontent-scalc-01.diff, kohei
diff --git a/patches/dev300/cws-graphite01-20081226.diff b/patches/dev300/cws-graphite01-20081226.diff
deleted file mode 100644
index 8f79f34..0000000
--- a/patches/dev300/cws-graphite01-20081226.diff
+++ /dev/null
@@ -1,5531 +0,0 @@
-Index: vcl/source/gdi/makefile.mk
-===================================================================
---- vcl/source/gdi/makefile.mk	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/source/gdi/makefile.mk	(.../cws/graphite01)	(Revision 265804)
-@@ -45,6 +45,9 @@
- .IF "$(COM)"=="ICC"
- CDEFS+=-D_STD_NO_NAMESPACE -D_VOS_NO_NAMESPACE -D_UNO_NO_NAMESPACE
- .ENDIF
-+.IF "$(ENABLE_GRAPHITE)" == "TRUE"
-+CDEFS+=-DENABLE_GRAPHITE
-+.ENDIF
- 
- # --- Files --------------------------------------------------------
- 
-Index: vcl/source/gdi/outdev3.cxx
-===================================================================
---- vcl/source/gdi/outdev3.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/source/gdi/outdev3.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -67,6 +67,9 @@
- #ifndef _OSL_FILE_H
- #include <osl/file.h>
- #endif
-+#ifdef ENABLE_GRAPHITE
-+#include <vcl/graphite_features.hxx>
-+#endif
- 
- #include <vcl/unohelp.hxx>
- #include <pdfwriter_impl.hxx>
-@@ -2706,10 +2709,10 @@
-     mpFontData( NULL ),
-     mpFontEntry( NULL )
- {
--    maTargetName = maName;
--    
-     rFont.GetFontAttributes( *this );
- 
-+    maTargetName = maName;
-+
-     // normalize orientation between 0 and 3600
-     if( 3600 <= (unsigned)mnOrientation )
-     {
-@@ -2752,6 +2755,14 @@
-     // TODO: does it pay off to improve this hash function?
-     static FontNameHash aFontNameHash;
-     size_t nHash = aFontNameHash( rFSD.maSearchName );
-+#ifdef ENABLE_GRAPHITE
-+    // check for features and generate a unique hash if necessary
-+    if (rFSD.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
-+        != STRING_NOTFOUND)
-+    {
-+        nHash = aFontNameHash( rFSD.maTargetName );
-+    }
-+#endif
-     nHash += 11 * rFSD.mnHeight;
-     nHash += 19 * rFSD.meWeight;
-     nHash += 29 * rFSD.meItalic;
-@@ -2803,6 +2814,15 @@
-             return false;
-     }
- 
-+#ifdef ENABLE_GRAPHITE
-+    // check for features
-+    if ((rA.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
-+         != STRING_NOTFOUND ||
-+         rB.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
-+         != STRING_NOTFOUND) && rA.maTargetName != rB.maTargetName)
-+        return false;
-+#endif
-+
-     return true;
- }
- 
-@@ -2840,7 +2860,12 @@
-         // if it is already known get its normalized search name
-         FontNameList::const_iterator it_name = maFontNameList.find( aSearchName );
-         if( it_name != maFontNameList.end() )
--            if( !(*it_name).second.EqualsAscii( "hg", 0, 2) )
-+            if( !(*it_name).second.EqualsAscii( "hg", 0, 2)
-+#ifdef ENABLE_GRAPHITE
-+                && (aSearchName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
-+                    == STRING_NOTFOUND)
-+#endif
-+            )
-                 aSearchName = (*it_name).second;
-     }
- 
-@@ -2945,6 +2970,22 @@
-     {
-         rFSD.maTargetName = GetNextFontToken( rFSD.maName, nTokenPos );
-         aSearchName = rFSD.maTargetName;
-+
-+#ifdef ENABLE_GRAPHITE
-+        // Until features are properly supported, they are appended to the
-+        // font name, so we need to strip them off so the font is found.
-+        xub_StrLen nFeat = aSearchName.Search(grutils::GrFeatureParser::FEAT_PREFIX);
-+        String aOrigName = rFSD.maTargetName;
-+        String aBaseFontName(aSearchName, 0, (nFeat != STRING_NOTFOUND)?nFeat:aSearchName.Len());
-+        if (nFeat != STRING_NOTFOUND && STRING_NOTFOUND !=
-+            aSearchName.Search(grutils::GrFeatureParser::FEAT_ID_VALUE_SEPARATOR, nFeat))
-+        {
-+            aSearchName = aBaseFontName;
-+            rFSD.maTargetName = aBaseFontName;
-+        }
-+
-+#endif
-+
-         ImplGetEnglishSearchFontName( aSearchName );
-         ImplFontSubstitute( aSearchName, nSubstFlags, pDevSpecific );
-         // #114999# special emboldening for Ricoh fonts
-@@ -2981,7 +3022,11 @@
-         if( mpPreMatchHook )
-             if( mpPreMatchHook->FindFontSubstitute( rFSD ) )
-                 ImplGetEnglishSearchFontName( aSearchName );
--
-+#ifdef ENABLE_GRAPHITE
-+        // the prematch hook uses the target name to search, but we now need
-+        // to restore the features to make the font selection data unique
-+        rFSD.maTargetName = aOrigName;
-+#endif
-         // check if the current font name token or its substitute is valid
- 	ImplDevFontListData* pFoundData = ImplFindBySearchName( aSearchName );
-         if( pFoundData )
-@@ -5342,6 +5387,7 @@
-     DBG_CHKOBJ( &rNewFont, Font, NULL );
- 
-     Font aFont( rNewFont );
-+    aFont.SetLanguage(rNewFont.GetLanguage());
-     if ( mnDrawMode & (DRAWMODE_BLACKTEXT | DRAWMODE_WHITETEXT | DRAWMODE_GRAYTEXT | DRAWMODE_GHOSTEDTEXT | DRAWMODE_SETTINGSTEXT |
-                        DRAWMODE_BLACKFILL | DRAWMODE_WHITEFILL | DRAWMODE_GRAYFILL | DRAWMODE_NOFILL |
-                        DRAWMODE_GHOSTEDFILL | DRAWMODE_SETTINGSFILL ) )
-Index: vcl/source/gdi/sallayout.cxx
-===================================================================
---- vcl/source/gdi/sallayout.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/source/gdi/sallayout.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -1107,6 +1107,8 @@
-     for( int nCharPos = i = -1; rArgs.GetNextPos( &nCharPos, &bRTL ); )
-     {
-         n = nCharPos - rArgs.mnMinCharPos;
-+        if( (n < 0) || (nCharCount <= n) )  continue;
-+
-         if( pLogCluster[ n ] >= 0 )
-             i = pLogCluster[ n ];
-         if( i >= 0 )
-@@ -1695,6 +1697,19 @@
-         }
-     }
- 
-+    // Compute rtl flags, since in some scripts glyphs/char order can be
-+    // reversed for a few character sequencies e.g. Myanmar
-+    std::vector<bool> vRtl(rArgs.mnEndCharPos - rArgs.mnMinCharPos, false);
-+    rArgs.ResetPos();
-+    bool bRtl;
-+    int nRunStart, nRunEnd;
-+    while (rArgs.GetNextRun(&nRunStart, &nRunEnd, &bRtl))
-+    {
-+        if (bRtl) std::fill(vRtl.begin() + nRunStart - rArgs.mnMinCharPos,
-+                            vRtl.begin() + nRunEnd - rArgs.mnMinCharPos, true);
-+    }
-+    rArgs.ResetPos();
-+
-     // prepare "merge sort"
-     int nStartOld[ MAX_FALLBACK ];
-     int nStartNew[ MAX_FALLBACK ];
-@@ -1728,6 +1743,10 @@
-         nStartNew[ nLevel ] = nStartOld[ nLevel ] = 0;
-         nValid[ nLevel ] = mpLayouts[n]->GetNextGlyphs( 1, &nDummy, aPos,
-             nStartNew[ nLevel ], &nGlyphAdv[ nLevel ], &nCharPos[ nLevel ] );
-+#ifdef MULTI_SL_DEBUG
-+        if (nValid[nLevel]) printf("layout[%d]->GetNextGlyphs %d,%d x%d a%d c%d %x\n", n, nStartOld[n], nStartNew[n], aPos.X(), nGlyphAdv[n], nCharPos[n],
-+            rArgs.mpStr[nCharPos[n]]);
-+#endif
-         if( (n > 0) && !nValid[ nLevel ] )
-         {
-             // an empty fallback layout can be released
-@@ -1753,6 +1772,9 @@
-     for( n = 0; n < nLevel; ++n )
-         maFallbackRuns[n].ResetPos();
-     int nActiveCharPos = nCharPos[0];
-+    int nLastRunEndChar = (vRtl[nActiveCharPos - mnMinCharPos])?
-+        rArgs.mnEndCharPos : rArgs.mnMinCharPos - 1;
-+    int nRunVisibleEndChar = nCharPos[0];
-     while( nValid[0] && (nLevel > 0))
-     {
-         // find best fallback level
-@@ -1788,6 +1810,9 @@
-                 nStartOld[0] = nStartNew[0];
-                 nValid[0] = mpLayouts[0]->GetNextGlyphs( 1, &nDummy, aPos,
-                     nStartNew[0], &nGlyphAdv[0], &nCharPos[0] );
-+#ifdef MULTI_SL_DEBUG
-+                if (nValid[0]) printf("layout[0]->GetNextGlyphs %d,%d x%d a%d c%d %x\n", nStartOld[0], nStartNew[0], aPos.X(), nGlyphAdv[0], nCharPos[0], rArgs.mpStr[nCharPos[0]]);
-+#endif
-                 if( !nValid[0] )
-                    break;
-             }
-@@ -1805,7 +1830,9 @@
-             int nOrigCharPos = nCharPos[n];
-             nValid[n] = mpLayouts[n]->GetNextGlyphs( 1, &nDummy, aPos,
-                 nStartNew[n], &nGlyphAdv[n], &nCharPos[n] );
--
-+#ifdef MULTI_SL_DEBUG
-+            if (nValid[n]) printf("layout[%d]->GetNextGlyphs %d,%d a%d c%d %x\n", n, nStartOld[n], nStartNew[n], nGlyphAdv[n], nCharPos[n], rArgs.mpStr[nCharPos[n]]);
-+#endif
-             // break after last glyph of active layout
-             if( !nValid[n] )
-             {
-@@ -1851,6 +1878,27 @@
-                     { maFallbackRuns[0].NextRun(); break; }
-                 bKeepNotDef = bNeedFallback;
-             }
-+            // check for reordered glyphs
-+            if (aMultiArgs.mpDXArray &&
-+                nRunVisibleEndChar < mnEndCharPos &&
-+                nRunVisibleEndChar >= mnMinCharPos &&
-+                nCharPos[n] < mnEndCharPos &&
-+                nCharPos[n] >= mnMinCharPos)
-+            {
-+                if (vRtl[nActiveCharPos - mnMinCharPos])
-+                {
-+                    if (aMultiArgs.mpDXArray[nRunVisibleEndChar-mnMinCharPos]
-+                        >= aMultiArgs.mpDXArray[nCharPos[n] - mnMinCharPos])
-+                    {
-+                        nRunVisibleEndChar = nCharPos[n];
-+                    }
-+                }
-+                else if (aMultiArgs.mpDXArray[nRunVisibleEndChar-mnMinCharPos]
-+                         <= aMultiArgs.mpDXArray[nCharPos[n] - mnMinCharPos])
-+                {
-+                    nRunVisibleEndChar = nCharPos[n];
-+                }
-+            }
-         }
- 
-         // if a justification array is available
-@@ -1860,16 +1908,40 @@
-             // the run advance is the width from the first char
-             // in the run to the first char in the next run
-             nRunAdvance = 0;
--            const bool bLTR = (nActiveCharPos < nCharPos[0]);
-+#ifdef MULTI_SL_DEBUG
-+            const bool bLTR = !(vRtl[nActiveCharPos - mnMinCharPos]);//(nActiveCharPos < nCharPos[0]);
-+            int nOldRunAdv = 0;
-             int nDXIndex = nCharPos[0] - mnMinCharPos - bLTR;
-             if( nDXIndex >= 0 )
--                nRunAdvance += aMultiArgs.mpDXArray[ nDXIndex ];
-+                nOldRunAdv += aMultiArgs.mpDXArray[ nDXIndex ];
-             nDXIndex = nActiveCharPos - mnMinCharPos - bLTR;
-             if( nDXIndex >= 0 )
--                nRunAdvance -= aMultiArgs.mpDXArray[ nDXIndex ];
-+                nOldRunAdv -= aMultiArgs.mpDXArray[ nDXIndex ];
-             if( !bLTR )
--                nRunAdvance = -nRunAdvance;
--
-+                nOldRunAdv = -nOldRunAdv;
-+#endif
-+            if (vRtl[nActiveCharPos - mnMinCharPos])
-+            {
-+              if (nRunVisibleEndChar > mnMinCharPos && nRunVisibleEndChar <= mnEndCharPos)
-+                  nRunAdvance -= aMultiArgs.mpDXArray[nRunVisibleEndChar - 1 - mnMinCharPos];
-+              if (nLastRunEndChar > mnMinCharPos && nLastRunEndChar <= mnEndCharPos)
-+                  nRunAdvance += aMultiArgs.mpDXArray[nLastRunEndChar - 1 - mnMinCharPos];
-+#ifdef MULTI_SL_DEBUG
-+              printf("rtl visible %d-%d,%d-%d adv%d(%d)\n", nLastRunEndChar-1, nRunVisibleEndChar-1, nActiveCharPos - bLTR, nCharPos[0] - bLTR, nRunAdvance, nOldRunAdv);
-+#endif
-+            }
-+            else
-+            {
-+                if (nRunVisibleEndChar >= mnMinCharPos)
-+                  nRunAdvance += aMultiArgs.mpDXArray[nRunVisibleEndChar - mnMinCharPos];
-+                if (nLastRunEndChar >= mnMinCharPos)
-+                  nRunAdvance -= aMultiArgs.mpDXArray[nLastRunEndChar - mnMinCharPos];
-+#ifdef MULTI_SL_DEBUG
-+                printf("visible %d-%d,%d-%d adv%d(%d)\n", nLastRunEndChar, nRunVisibleEndChar, nActiveCharPos - bLTR, nCharPos[0] - bLTR, nRunAdvance, nOldRunAdv);
-+#endif
-+            }
-+            nLastRunEndChar = nRunVisibleEndChar;
-+            nRunVisibleEndChar = nCharPos[0];
-             // the requested width is still in pixel units
-             // => convert it to base level font units
-             nRunAdvance *= mnUnitsPerPixel;
-@@ -1887,9 +1959,27 @@
- 
-         // prepare for next fallback run
-         nActiveCharPos = nCharPos[0];
-+        // it essential that the runs don't get ahead of themselves and in the
-+        // if( bKeepNotDef && !bNeedFallback ) statement above, the next run may
-+        // have already been reached on the base level
-         for( int i = nFBLevel; --i >= 0;)
--            if( !maFallbackRuns[i].PosIsInRun( nActiveCharPos ) )
--                maFallbackRuns[i].NextRun();
-+        {
-+            if (maFallbackRuns[i].GetRun(&nRunStart, &nRunEnd, &bRtl))
-+            {
-+                if (bRtl)
-+                {
-+                    if (nRunStart > nActiveCharPos)
-+                        maFallbackRuns[i].NextRun();
-+                }
-+                else
-+                {
-+                    if (nRunEnd <= nActiveCharPos)
-+                        maFallbackRuns[i].NextRun();
-+                }
-+            }
-+        }
-+//            if( !maFallbackRuns[i].PosIsInRun( nActiveCharPos ) )
-+//                maFallbackRuns[i].NextRun();
-     }
- 
-     mpLayouts[0]->Simplify( true );
-Index: vcl/source/glyphs/graphite_textsrc.cxx
-===================================================================
---- vcl/source/glyphs/graphite_textsrc.cxx	(.../tags/DEV300_m35)	(Revision 0)
-+++ vcl/source/glyphs/graphite_textsrc.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,155 @@
-+//
-+// C++ Implementation: Graphite to SAL adaptor classes
-+//
-+// Description: Implements the Graphite interfaces IGrTextSource and
-+//              IGrGraphics which provide Graphite with access to the
-+//              app's text storage system and the platform's font and
-+//              graphics systems.
-+//
-+// Author: Tim Eves <tim_eves at sil.org>
-+//
-+// Copyright: Copyright (C) 2003-2004 SIL International.
-+//            All rights reserved. Distributable under the terms of either
-+//            the Common Public License or the GNU Lesser General Public
-+//            License.
-+//
-+
-+// We need this to enable namespace support in libgrengine headers.
-+#define GR_NAMESPACE
-+
-+// Header files
-+//
-+// Standard Library
-+#include <string>
-+#include <cassert>
-+#include "graphite_textsrc.hxx"
-+#include <vcl/graphite_features.hxx>
-+
-+// class TextSourceAdaptor implementation.
-+//
-+TextSourceAdaptor::~TextSourceAdaptor()
-+{
-+    delete mpFeatures;
-+}
-+
-+gr::UtfType TextSourceAdaptor::utfEncodingForm() {
-+    return gr::kutf16;
-+}
-+
-+
-+size_t TextSourceAdaptor::getLength()
-+{
-+    return maLayoutArgs.mnLength;
-+}
-+
-+
-+size_t  TextSourceAdaptor::fetch(gr::toffset, size_t, gr::utf32 *)
-+{
-+    assert(false);
-+    return 0;
-+}
-+
-+
-+size_t  TextSourceAdaptor::fetch(gr::toffset offset, size_t char_count, gr::utf16 * char_buffer)
-+{
-+  assert(char_buf);
-+
-+  size_t copy_count =  std::min(size_t(maLayoutArgs.mnLength), char_count);
-+  std::copy(maLayoutArgs.mpStr + offset, maLayoutArgs.mpStr + offset + copy_count, char_buffer);
-+
-+  return copy_count;
-+}
-+
-+
-+size_t TextSourceAdaptor::fetch(gr::toffset, size_t, gr::utf8  *)
-+{
-+    assert(false);
-+    return 0;
-+}
-+
-+
-+inline void TextSourceAdaptor::getCharProperties(const int nCharIdx, int & min, int & lim, size_t & depth)
-+{
-+    maLayoutArgs.ResetPos();
-+    bool rtl = maLayoutArgs.mnFlags & SAL_LAYOUT_BIDI_RTL;
-+    for(depth = ((rtl)? 1:0); maLayoutArgs.maRuns.GetRun(&min, &lim, &rtl); maLayoutArgs.maRuns.NextRun())
-+    {
-+        if (min > nCharIdx)
-+            break;
-+        // Only increase the depth when a change of direction occurs.
-+        depth += int(rtl ^ bool(depth & 0x1));
-+        if (min <= nCharIdx && nCharIdx < lim)
-+            break;
-+    }
-+    // If there is no run for this position increment the depth, but don't
-+    // change if this is out of bounds context
-+    if (lim > 0 && nCharIdx >= lim && nCharIdx < maLayoutArgs.mnEndCharPos)
-+        depth++;
-+}
-+
-+
-+bool TextSourceAdaptor::getRightToLeft(gr::toffset nCharIdx)
-+{
-+    size_t depth;
-+    int min, lim = 0;
-+    getCharProperties(nCharIdx, min, lim, depth);
-+    //printf("getRtl %d,%x=%d\n", nCharIdx, maLayoutArgs.mpStr[nCharIdx], depth & 0x1);
-+    return depth & 0x1;
-+}
-+
-+
-+unsigned int TextSourceAdaptor::getDirectionDepth(gr::toffset nCharIdx)
-+{
-+    size_t depth;
-+    int min, lim;
-+    getCharProperties(nCharIdx, min, lim, depth);
-+    //printf("getDirectionDepth %d,%x=%d\n", nCharIdx, maLayoutArgs.mpStr[nCharIdx], depth);
-+    return depth;
-+}
-+
-+
-+float TextSourceAdaptor::getVerticalOffset(gr::toffset)
-+{
-+    return 0.0f;    //TODO: Implement correctly
-+}
-+
-+gr::isocode TextSourceAdaptor::getLanguage(gr::toffset)
-+{
-+    if (mpFeatures && mpFeatures->hasLanguage())
-+        return mpFeatures->getLanguage();
-+    gr::isocode unknown = {{0,0,0,0}};
-+    return unknown;
-+}
-+
-+std::pair<gr::toffset, gr::toffset> TextSourceAdaptor::propertyRange(gr::toffset nCharIdx)
-+{
-+
-+    if (nCharIdx < unsigned(maLayoutArgs.mnMinCharPos))
-+        return std::make_pair(0, maLayoutArgs.mnMinCharPos);
-+
-+    if (nCharIdx < mnEnd)
-+        return std::make_pair(maLayoutArgs.mnMinCharPos, mnEnd);
-+
-+    return std::make_pair(mnEnd, maLayoutArgs.mnLength);
-+}
-+
-+size_t TextSourceAdaptor::getFontFeatures(gr::toffset, gr::FeatureSetting * settings)
-+{
-+    if (mpFeatures) return mpFeatures->getFontFeatures(settings);
-+    return 0;
-+}
-+
-+
-+bool TextSourceAdaptor::sameSegment(gr::toffset char_idx1, gr::toffset char_idx2)
-+{
-+    const std::pair<gr::toffset, gr::toffset>
-+    range1 = propertyRange(char_idx1),
-+    range2 = propertyRange(char_idx2);
-+
-+    return range1 == range2;
-+}
-+
-+void TextSourceAdaptor::setFeatures(const grutils::GrFeatureParser * pFeatures)
-+{
-+    mpFeatures = new grutils::GrFeatureParser(*pFeatures);
-+}
-Index: vcl/source/glyphs/graphite_adaptors.cxx
-===================================================================
---- vcl/source/glyphs/graphite_adaptors.cxx	(.../tags/DEV300_m35)	(Revision 0)
-+++ vcl/source/glyphs/graphite_adaptors.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,293 @@
-+//
-+// C++ Implementation: Graphite to SAL adaptor classes
-+//
-+// Description: Implements the Graphite interfaces IGrTextSource and
-+//              IGrGraphics which provide Graphite with access to the
-+//              app's text storage system and the platform's font and
-+//              graphics systems.
-+//
-+// Author: Tim Eves <tim_eves at sil.org>
-+//
-+// Copyright: Copyright (C) 2003-2004 SIL International.
-+//            All rights reserved. Distributable under the terms of either
-+//            the Common Public License or the GNU Lesser General Public
-+//            License.
-+//
-+
-+// We need this to enable namespace support in libgrengine headers.
-+#define GR_NAMESPACE
-+
-+// Header files
-+//
-+// Standard Library
-+#include <string>
-+#include <cassert>
-+// Libraries
-+#include <rtl/string.hxx>
-+#include <rtl/ustring.hxx>
-+#include <i18npool/mslangid.hxx>
-+// Platform
-+#ifndef MSC
-+#include <saldisp.hxx>
-+
-+#include <vcl/salgdi.hxx>
-+
-+#include <freetype/ftsynth.h>
-+
-+// Module
-+#include "gcach_ftyp.hxx"
-+
-+#include <vcl/graphite_features.hxx>
-+#include <vcl/graphite_adaptors.hxx>
-+
-+// Module private type definitions and forward declarations.
-+//
-+using gr::GrResult;
-+namespace
-+{
-+    inline float from_hinted(const int x) {
-+        return static_cast<float>(x + 32) / 64.0;
-+    }
-+    typedef std::hash_map<long,bool> SilfMap;
-+    SilfMap sSilfMap;
-+}
-+
-+// class CharacterRenderProperties implentation.
-+//
-+FontProperties::FontProperties(const FreetypeServerFont &font) throw()
-+{
-+    clrFore = gr::kclrBlack;
-+    clrBack = gr::kclrTransparent;
-+
-+    pixHeight = from_hinted(font.GetMetricsFT().height);
-+
-+    switch (font.GetFontSelData().meWeight)
-+    {
-+        case WEIGHT_SEMIBOLD: case WEIGHT_BOLD:
-+        case WEIGHT_ULTRABOLD: case WEIGHT_BLACK:
-+            fBold = true;
-+            break;
-+        default :
-+            fBold = false;
-+    }
-+
-+    switch (font.GetFontSelData().meItalic)
-+    {
-+        case ITALIC_NORMAL: case ITALIC_OBLIQUE:
-+            fItalic = true;
-+            break;
-+        default :
-+            fItalic = false;
-+    }
-+
-+    // Get the font name.
-+    const sal_Unicode    * name = font.GetFontSelData().maName.GetBuffer();
-+    const size_t          name_sz = std::min(sizeof szFaceName/sizeof(wchar_t)-1,
-+                    size_t(font.GetFontSelData().maName.Len()));
-+
-+    std::copy(name, name + name_sz, szFaceName);
-+    szFaceName[name_sz] = '\0';
-+}
-+
-+// class GraphiteFontAdaptor implementaion.
-+//
-+GraphiteFontAdaptor::GraphiteFontAdaptor(ServerFont & sfont, const sal_Int32 dpiX, const sal_Int32 dpiY)
-+  :    mrFont(static_cast<FreetypeServerFont &>(sfont)),
-+    maFontProperties(static_cast<FreetypeServerFont &>(sfont)),
-+    mnDpiX(dpiX),
-+    mnDpiY(dpiY),
-+    mfAscent(from_hinted(static_cast<FreetypeServerFont &>(sfont).GetMetricsFT().ascender)),
-+    mfDescent(from_hinted(static_cast<FreetypeServerFont &>(sfont).GetMetricsFT().descender)),
-+    mfEmUnits(static_cast<FreetypeServerFont &>(sfont).GetMetricsFT().y_ppem),
-+    mpFeatures(NULL)
-+{
-+    //std::wstring face_name(maFontProperties.szFaceName);
-+    const rtl::OString aLang = MsLangId::convertLanguageToIsoByteString( sfont.GetFontSelData().meLanguage );
-+#ifdef DEBUG
-+    printf("GraphiteFontAdaptor %lx\n", (long)this);
-+#endif
-+    rtl::OString name = rtl::OUStringToOString(
-+        sfont.GetFontSelData().maTargetName, RTL_TEXTENCODING_UTF8 );
-+    sal_Int32 nFeat = name.indexOf(grutils::GrFeatureParser::FEAT_PREFIX) + 1;
-+    if (nFeat > 0)
-+    {
-+        rtl::OString aFeat = name.copy(nFeat, name.getLength() - nFeat);
-+        mpFeatures = new grutils::GrFeatureParser(*this, aFeat.getStr(), aLang.getStr());
-+#ifdef DEBUG
-+        printf("GraphiteFontAdaptor %s/%s/%s %x language %d features %d errors\n",
-+            rtl::OUStringToOString( sfont.GetFontSelData().maName,
-+            RTL_TEXTENCODING_UTF8 ).getStr(),
-+            rtl::OUStringToOString( sfont.GetFontSelData().maTargetName,
-+            RTL_TEXTENCODING_UTF8 ).getStr(),
-+            rtl::OUStringToOString( sfont.GetFontSelData().maSearchName,
-+            RTL_TEXTENCODING_UTF8 ).getStr(),
-+            sfont.GetFontSelData().meLanguage,
-+            (int)mpFeatures->getFontFeatures(NULL), mpFeatures->parseErrors());
-+#endif
-+    }
-+    else
-+    {
-+        mpFeatures = new grutils::GrFeatureParser(*this, aLang.getStr());
-+    }
-+}
-+
-+GraphiteFontAdaptor::GraphiteFontAdaptor(const GraphiteFontAdaptor &rhs) throw()
-+ :    Font(rhs),
-+     mrFont (rhs.mrFont), maFontProperties(rhs.maFontProperties),
-+    mnDpiX(rhs.mnDpiX), mnDpiY(rhs.mnDpiY),
-+    mfAscent(rhs.mfAscent), mfDescent(rhs.mfDescent), mfEmUnits(rhs.mfEmUnits),
-+    mpFeatures(NULL)
-+{
-+    if (rhs.mpFeatures) mpFeatures = new grutils::GrFeatureParser(*(rhs.mpFeatures));
-+}
-+
-+
-+GraphiteFontAdaptor::~GraphiteFontAdaptor() throw()
-+{
-+    maGlyphMetricMap.clear();
-+    if (mpFeatures) delete mpFeatures;
-+    mpFeatures = NULL;
-+}
-+
-+void GraphiteFontAdaptor::UniqueCacheInfo(std::wstring & face_name_out, bool & bold_out, bool & italic_out)
-+{
-+    face_name_out = maFontProperties.szFaceName;
-+    bold_out = maFontProperties.fBold;
-+    italic_out = maFontProperties.fItalic;
-+}
-+
-+bool GraphiteFontAdaptor::IsGraphiteEnabledFont(ServerFont & font) throw()
-+{
-+    // NOTE: this assumes that the same FTFace pointer won't be reused,
-+    // so FtFontInfo::ReleaseFaceFT must only be called at shutdown.
-+    FreetypeServerFont & aFtFont = static_cast<FreetypeServerFont &>(font);
-+    SilfMap::iterator i = sSilfMap.find(reinterpret_cast<long>(aFtFont.GetFtFace()));
-+    if (i != sSilfMap.end()) return (*i).second;
-+    bool bHasSilf = aFtFont.GetTable("Silf", 0);
-+    sSilfMap[reinterpret_cast<long>(aFtFont.GetFtFace())] = bHasSilf;
-+    return bHasSilf;
-+}
-+
-+
-+gr::Font * GraphiteFontAdaptor::copyThis() {
-+    return new GraphiteFontAdaptor(*this);
-+}
-+
-+
-+unsigned int GraphiteFontAdaptor::getDPIx() {
-+    return mnDpiX;
-+}
-+
-+
-+unsigned int GraphiteFontAdaptor::getDPIy() {
-+    return mnDpiY;
-+}
-+
-+
-+float GraphiteFontAdaptor::ascent() {
-+    return mfAscent;
-+}
-+
-+
-+float GraphiteFontAdaptor::descent() {
-+    return mfDescent;
-+}
-+
-+
-+bool GraphiteFontAdaptor::bold() {
-+    return maFontProperties.fBold;
-+}
-+
-+
-+bool GraphiteFontAdaptor::italic() {
-+    return maFontProperties.fItalic;
-+}
-+
-+
-+float GraphiteFontAdaptor::height() {
-+    return maFontProperties.pixHeight;
-+}
-+
-+
-+void GraphiteFontAdaptor::getFontMetrics(float * ascent_out, float * descent_out, float * em_square_out) {
-+    if (ascent_out)        *ascent_out    = mfAscent;
-+    if (descent_out)    *descent_out   = mfDescent;
-+    if (em_square_out)    *em_square_out = mfEmUnits;
-+}
-+
-+
-+const void * GraphiteFontAdaptor::getTable(gr::fontTableId32 table_id, size_t * buffer_sz)
-+{
-+    char tag_name[5] = {char(table_id >> 24), char(table_id >> 16), char(table_id >> 8), char(table_id), 0};
-+    ULONG temp = *buffer_sz;
-+
-+    const void * const tbl_buf = static_cast<FreetypeServerFont &>(mrFont).GetTable(tag_name, &temp);
-+    *buffer_sz = temp;
-+
-+    return tbl_buf;
-+}
-+
-+#define fix26_6(x) (x >> 6) + (x & 32 ? (x > 0 ? 1 : 0) : (x < 0 ? -1 : 0))
-+
-+// Return the glyph's metrics in pixels.
-+void GraphiteFontAdaptor::getGlyphMetrics(gr::gid16 nGlyphId, gr::Rect & aBounding, gr::Point & advances)
-+{
-+    // Graphite gets really confused if the glyphs have been transformed, so
-+    // if orientation has been set we can't use the font's glyph cache
-+    // unfortunately the font selection data, doesn't always have the orientation
-+    // set, even if it was when the glyphs were cached, so we use our own cache.
-+
-+//         const GlyphMetric & metric = mrFont.GetGlyphMetric(nGlyphId);
-+//
-+//         aBounding.right  = aBounding.left = metric.GetOffset().X();
-+//         aBounding.bottom = aBounding.top  = -metric.GetOffset().Y();
-+//         aBounding.right  += metric.GetSize().Width();
-+//         aBounding.bottom -= metric.GetSize().Height();
-+//
-+//         advances.x = metric.GetDelta().X();
-+//         advances.y = -metric.GetDelta().Y();
-+
-+    GlyphMetricMap::const_iterator gm_itr = maGlyphMetricMap.find(nGlyphId);
-+    if (gm_itr != maGlyphMetricMap.end())
-+    {
-+        // We've cached the results from last time.
-+        aBounding = gm_itr->second.first;
-+        advances    = gm_itr->second.second;
-+    }
-+    else
-+    {
-+        // We need to look up the glyph.
-+        FT_Int nLoadFlags = mrFont.GetLoadFlags();
-+
-+        FT_Face aFace = reinterpret_cast<FT_Face>(mrFont.GetFtFace());
-+        FT_Error aStatus = -1;
-+        aStatus = FT_Load_Glyph(aFace, nGlyphId, nLoadFlags);
-+        if( aStatus != FT_Err_Ok )
-+        {
-+            aBounding.top = aBounding.bottom = aBounding.left = aBounding.right = 0;
-+            advances.x = advances.y = 0;
-+            return;
-+        }
-+        // check whether we need synthetic bold/italic otherwise metric is wrong
-+        if (mrFont.NeedsArtificialBold())
-+            FT_GlyphSlot_Embolden(aFace->glyph);
-+
-+        if (mrFont.NeedsArtificialItalic())
-+            FT_GlyphSlot_Oblique(aFace->glyph);
-+
-+        const FT_Glyph_Metrics &gm = aFace->glyph->metrics;
-+
-+        // Fill out the bounding box an advances.
-+        aBounding.top = aBounding.bottom = fix26_6(gm.horiBearingY);
-+        aBounding.bottom -= fix26_6(gm.height);
-+        aBounding.left = aBounding.right = fix26_6(gm.horiBearingX);
-+        aBounding.right += fix26_6(gm.width);
-+        advances.x = fix26_6(gm.horiAdvance);
-+        advances.y = 0;
-+
-+        // Now add an entry to our metrics map.
-+        maGlyphMetricMap[nGlyphId] = std::make_pair(aBounding, advances);
-+    }
-+}
-+
-+#endif
-Index: vcl/source/glyphs/graphite_layout.cxx
-===================================================================
---- vcl/source/glyphs/graphite_layout.cxx	(.../tags/DEV300_m35)	(Revision 0)
-+++ vcl/source/glyphs/graphite_layout.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,1229 @@
-+//
-+// C++ Implementation: GraphiteLayout
-+//
-+// Description: An implementation of the SalLayout interface that uses the
-+//              Graphite engine.
-+//
-+// Author: Tim Eves <tim_eves at sil.org>
-+//         Keith Stribley <devel at thanlwinsoft.org>
-+//
-+// Copyright: Copyright (C) 2003,2008 SIL International.
-+//            All rights reserved. Distributable under the terms of either
-+//            the Common Public License or the GNU Lesser General Public
-+//            License.
-+//
-+
-+// We need this to enable namespace support in libgrengine headers.
-+#define GR_NAMESPACE
-+
-+// Enable lots of debug info
-+#ifdef DEBUG
-+#define GRLAYOUT_DEBUG 1
-+//#undef NDEBUG
-+#endif
-+
-+// Header files
-+//
-+// Standard Library
-+#include <algorithm>
-+#include <cassert>
-+#include <functional>
-+#include <limits>
-+#include <numeric>
-+#include <deque>
-+// Platform
-+#ifdef MSC
-+#include <tools/svwin.h>
-+#include <svsys.h>
-+#endif
-+
-+#include <vcl/salgdi.hxx>
-+
-+#include <unicode/uchar.h>
-+#include <unicode/ubidi.h>
-+
-+// Graphite Libraries (must be after vcl headers on windows)
-+#include <graphite/GrClient.h>
-+#include <graphite/Font.h>
-+#include <graphite/ITextSource.h>
-+#include <graphite/Segment.h>
-+#include <graphite/SegmentPainter.h>
-+
-+#include <vcl/graphite_layout.hxx>
-+#include <vcl/graphite_features.hxx>
-+#include "graphite_textsrc.hxx"
-+
-+
-+// Module private type definitions and forward declarations.
-+//
-+// Module private names.
-+//
-+
-+#ifdef GRLAYOUT_DEBUG
-+FILE * grLogFile = NULL;
-+FILE * grLog()
-+{
-+#ifdef MSC
-+  if (grLogFile == NULL) grLogFile = fopen("graphitelayout.log","w");
-+  else fflush(grLogFile);
-+  return grLogFile;
-+#else
-+  return stdout;
-+#endif
-+}
-+#endif
-+
-+#ifdef GRCACHE
-+#include <vcl/graphite_cache.hxx>
-+#endif
-+
-+
-+namespace
-+{
-+    typedef std::pair<gr::GlyphIterator, gr::GlyphIterator>       glyph_range_t;
-+    typedef std::pair<gr::GlyphSetIterator, gr::GlyphSetIterator> glyph_set_range_t;
-+
-+    inline long round(const float n) {
-+        return long(n + (n < 0 ? -0.5 : 0.5));
-+    }
-+
-+
-+    template<typename T>
-+    inline bool in_range(const T i, const T b, const T e) {
-+        return !(b > i) && i < e;
-+    }
-+
-+
-+    template<typename T>
-+    inline bool is_subrange(const T sb, const T se, const T b, const T e) {
-+        return !(b > sb || se > e);
-+    }
-+
-+
-+    template<typename T>
-+    inline bool is_subrange(const std::pair<T, T> &s, const T b, const T e) {
-+        return is_subrange(s.first, s.second, b, e);
-+    }
-+
-+    int findSameDirLimit(const xub_Unicode* buffer, int charCount, bool rtl)
-+    {
-+        UErrorCode status = U_ZERO_ERROR;
-+        UBiDi *ubidi = ubidi_openSized(charCount, 0, &status);
-+        int limit = 0;
-+        ubidi_setPara(ubidi, buffer, charCount,
-+            (rtl)?UBIDI_DEFAULT_RTL:UBIDI_DEFAULT_LTR, NULL, &status);
-+        UBiDiLevel level = 0;
-+        ubidi_getLogicalRun(ubidi, 0, &limit, &level);
-+        ubidi_close(ubidi);
-+        if ((rtl && !(level & 1)) || (!rtl && (level & 1)))
-+        {
-+            limit = 0;
-+        }
-+        return limit;
-+    }
-+
-+} // namespace
-+
-+
-+
-+// Impementation of the GraphiteLayout::Glyphs container class.
-+//    This is an extended vector class with methods added to enable
-+//        o Correctly filling with glyphs.
-+//        o Querying clustering relationships.
-+//        o manipulations that affect neighouring glyphs.
-+
-+const int GraphiteLayout::EXTRA_CONTEXT_LENGTH = 10;
-+#ifdef GRCACHE
-+GraphiteCacheHandler GraphiteCacheHandler::instance;
-+#endif
-+
-+// The Graphite glyph stream is really a sequence of glyph attachment trees
-+//  each rooted at a non-attached base glyph.  fill_from walks the glyph stream
-+//  find each non-attached base glyph and calls append to record them as a
-+//  sequence of clusters.
-+void
-+GraphiteLayout::Glyphs::fill_from(gr::Segment & rSegment, ImplLayoutArgs &rArgs,
-+    bool bRtl, long &rWidth, float fScaling, std::vector<int> & rChar2Base, std::vector<int> & rGlyph2Char, std::vector<int> & rCharDxs)
-+{
-+    // Create a glyph item for each of the glyph and append it to the base class glyph list.
-+    typedef std::pair< gr::GlyphSetIterator, gr::GlyphSetIterator > GrGlyphSet;
-+    int nChar = rArgs.mnEndCharPos - rArgs.mnMinCharPos;
-+    glyph_range_t iGlyphs = rSegment.glyphs();
-+    int nGlyphs = iGlyphs.second - iGlyphs.first;
-+    gr::GlyphIterator prevBase = iGlyphs.second;
-+    float fMinX = rSegment.advanceWidth();
-+    float fMaxX = 0.0f;
-+    rGlyph2Char.assign(nGlyphs, -1);
-+    long nDxOffset = 0;
-+    int nGlyphIndex = (bRtl)? (nGlyphs - 1) : 0;
-+    // OOo always expects the glyphs in ltr order
-+    int nDelta = (bRtl)? -1 : 1;
-+
-+    int nLastGlyph = (bRtl)? nGlyphs - 1: 0;
-+    int nNextChar = (bRtl)? (rSegment.stopCharacter() - 1) : rSegment.startCharacter();//rArgs.mnMinCharPos;
-+    // current glyph number (Graphite glyphs)
-+    //int currGlyph = 0;
-+    int nFirstCharInCluster = nNextChar;
-+    int nFirstGlyphInCluster = nLastGlyph;
-+
-+    // ltr first char in cluster is lowest, same is true for rtl
-+    // ltr first glyph in cluster is lowest, rtl first glyph is highest
-+
-+    // loop over the glyphs determining which characters are linked to them
-+    gr::GlyphIterator gi;
-+    for (gi = iGlyphs.first + nGlyphIndex;
-+         nGlyphIndex >= 0 && nGlyphIndex < nGlyphs;
-+         nGlyphIndex+= nDelta, gi = iGlyphs.first + nGlyphIndex)
-+    {
-+        gr::GlyphInfo info = (*gi);
-+#ifdef GRLAYOUT_DEBUG
-+        fprintf(grLog(),"Glyph %d %f,%f\n", (int)info.logicalIndex(), info.origin(), info.yOffset());
-+#endif
-+        // the last character associated with this glyph is after
-+        // our current cluster buffer position
-+        if ((bRtl && ((signed)info.firstChar() <= nNextChar)) ||
-+            (!bRtl && ((signed)info.lastChar() >= nNextChar)))
-+        {
-+            if ((bRtl && nGlyphIndex < nLastGlyph) ||
-+                (!bRtl && nGlyphIndex > nLastGlyph))
-+            {
-+                // this glyph is after the previous one left->right
-+                // if insertion is allowed before it then we are in a
-+                // new cluster
-+                int nAttachedBase = (*(info.attachedClusterBase())).logicalIndex();
-+                if (!info.isAttached() ||
-+                    !in_range(nAttachedBase, nFirstGlyphInCluster, nGlyphIndex))
-+                {
-+                    if (in_range(nFirstCharInCluster, rArgs.mnMinCharPos, rArgs.mnEndCharPos) &&
-+                        nFirstGlyphInCluster != nGlyphIndex)
-+                    {
-+                        std::pair <float,float> aBounds =
-+                            appendCluster(rSegment, rArgs, bRtl, nFirstCharInCluster,
-+                            nNextChar, nFirstGlyphInCluster, nGlyphIndex, fScaling,
-+                            rChar2Base, rGlyph2Char, rCharDxs, nDxOffset);
-+                        fMinX = std::min(aBounds.first, fMinX);
-+                        fMaxX = std::max(aBounds.second, fMaxX);
-+                    }
-+                    nFirstCharInCluster = (bRtl)? info.lastChar() : info.firstChar();
-+                    nFirstGlyphInCluster = nGlyphIndex;
-+                }
-+                nLastGlyph = (bRtl)? std::min(nGlyphIndex, nAttachedBase) :
-+                    std::max(nGlyphIndex, nAttachedBase);
-+            }
-+            // loop over chacters associated with this glyph and characters
-+            // between nextChar and the last character associated with this glyph
-+            // giving them the current cluster id.  This allows for character /glyph
-+            // order reversal.
-+            // For each character we do a reverse glyph id look up
-+            // and store the glyph id with the highest logical index in nLastGlyph
-+            while ((bRtl && ((signed)info.firstChar() <= nNextChar)) ||
-+                   (!bRtl && (signed)info.lastChar() >= nNextChar))
-+            {
-+                GrGlyphSet charGlyphs = rSegment.charToGlyphs(nNextChar);
-+                nNextChar += nDelta;
-+                gr::GlyphSetIterator gj = charGlyphs.first;
-+                while (gj != charGlyphs.second)
-+                {
-+                    nLastGlyph = (bRtl)? min(nLastGlyph, (signed)(*gj).logicalIndex()) : max(nLastGlyph, (signed)(*gj).logicalIndex());
-+                    ++gj;
-+                }
-+            }
-+            // if this is a rtl attached glyph, then we need to include its
-+            // base in the cluster, which will have a lower graphite index
-+            if (bRtl)
-+            {
-+                if ((signed)info.attachedClusterBase()->logicalIndex() < nLastGlyph)
-+                {
-+                    nLastGlyph = info.attachedClusterBase()->logicalIndex();
-+                }
-+            }
-+        }
-+
-+        // it is possible for the lastChar to be after nextChar and
-+        // firstChar to be before the nFirstCharInCluster in rare
-+        // circumstances e.g. Myanmar word for cemetery
-+        if ((bRtl && ((signed)info.lastChar() > nFirstCharInCluster)) ||
-+            (!bRtl && ((signed)info.firstChar() < nFirstCharInCluster)))
-+        {
-+            nFirstCharInCluster = info.firstChar();
-+        }
-+    }
-+    // process last cluster
-+    if (in_range(nFirstCharInCluster, rArgs.mnMinCharPos, rArgs.mnEndCharPos) &&
-+        nFirstGlyphInCluster != nGlyphIndex)
-+    {
-+        std::pair <float,float> aBounds =
-+            appendCluster(rSegment, rArgs, bRtl, nFirstCharInCluster, nNextChar,
-+                          nFirstGlyphInCluster, nGlyphIndex, fScaling,
-+                          rChar2Base, rGlyph2Char, rCharDxs, nDxOffset);
-+        fMinX = std::min(aBounds.first, fMinX);
-+        fMaxX = std::max(aBounds.second, fMaxX);
-+    }
-+    long nXOffset = round(fMinX * fScaling);
-+    rWidth = round(fMaxX * fScaling) - nXOffset + nDxOffset;
-+    // fill up non-base char dx with cluster widths from previous base glyph
-+    if (bRtl)
-+    {
-+        if (rCharDxs[nChar-1] == -1)
-+            rCharDxs[nChar-1] = 0;
-+        else
-+            rCharDxs[nChar-1] -= nXOffset;
-+        for (int i = nChar - 2; i >= 0; i--)
-+        {
-+            if (rCharDxs[i] == -1) rCharDxs[i] = rCharDxs[i+1];
-+            else rCharDxs[i] -= nXOffset;
-+        }
-+    }
-+    else
-+    {
-+        if (rCharDxs[0] == -1)
-+            rCharDxs[0] = 0;
-+        else
-+            rCharDxs[0] -= nXOffset;
-+        for (int i = 1; i < nChar; i++)
-+        {
-+            if (rCharDxs[i] == -1) rCharDxs[i] = rCharDxs[i-1];
-+            else rCharDxs[i] -= nXOffset;
-+        }
-+    }
-+#ifdef GRLAYOUT_DEBUG
-+    fprintf(grLog(),"Glyphs xOff%ld dropDx%ld w%ld\n", nXOffset, nDxOffset, rWidth);
-+#endif
-+    // remove offset due to context if there is one
-+    if (nXOffset != 0)
-+    {
-+        for (size_t i = 0; i < size(); i++)
-+            (*this)[i].maLinearPos.X() -= nXOffset;
-+    }
-+}
-+
-+std::pair<float,float> GraphiteLayout::Glyphs::appendCluster(gr::Segment & rSeg,
-+    ImplLayoutArgs & rArgs, bool bRtl, int nFirstCharInCluster, int nNextChar,
-+    int nFirstGlyphInCluster, int nNextGlyph, float fScaling,
-+    std::vector<int> & rChar2Base, std::vector<int> & rGlyph2Char,
-+    std::vector<int> & rCharDxs, long & rDXOffset)
-+{
-+    glyph_range_t iGlyphs = rSeg.glyphs();
-+    int nGlyphs = iGlyphs.second - iGlyphs.first;
-+    int nDelta = (bRtl)? -1 : 1;
-+    gr::GlyphInfo aFirstGlyph = *(iGlyphs.first + nFirstGlyphInCluster);
-+    std::pair <float, float> aBounds;
-+    aBounds.first = aFirstGlyph.origin();
-+    aBounds.second = aFirstGlyph.origin();
-+    // before we add the glyphs to this vector, we record the
-+    // glyph's index in the vector (which is not the same as
-+    // the Segment's glyph index!)
-+    assert(size() < rGlyph2Char.size());
-+    rChar2Base[nFirstCharInCluster-rArgs.mnMinCharPos] = size();
-+    rGlyph2Char[size()] = nFirstCharInCluster;
-+    bool bBaseGlyph = true;
-+    for (int j = nFirstGlyphInCluster;
-+        j != nNextGlyph; j += nDelta)
-+    {
-+        long nNextOrigin;
-+        float fNextOrigin;
-+        gr::GlyphInfo aGlyph = *(iGlyphs.first + j);
-+        if (j + nDelta >= nGlyphs || j + nDelta < 0) // at rhs ltr,rtl
-+        {
-+            fNextOrigin = rSeg.advanceWidth();
-+            nNextOrigin = round(rSeg.advanceWidth() * fScaling + rDXOffset);
-+            aBounds.second = std::max(rSeg.advanceWidth(), aBounds.second);
-+        }
-+        else
-+        {
-+            gr::GlyphInfo aNextGlyph = *(iGlyphs.first + j + nDelta);
-+            fNextOrigin = std::max(aNextGlyph.attachedClusterBase()->origin(), aNextGlyph.origin());
-+            aBounds.second = std::max(fNextOrigin, aBounds.second);
-+            nNextOrigin = round(fNextOrigin * fScaling + rDXOffset);
-+        }
-+        aBounds.first = std::min(aGlyph.origin(), aBounds.first);
-+        if ((signed)aGlyph.firstChar() < rArgs.mnEndCharPos &&
-+            (signed)aGlyph.firstChar() >= rArgs.mnMinCharPos)
-+        {
-+            rCharDxs[aGlyph.firstChar()-rArgs.mnMinCharPos] = nNextOrigin;
-+        }
-+        if ((signed)aGlyph.attachedClusterBase()->logicalIndex() == j)
-+        {
-+            append(rSeg, rArgs, aGlyph, fNextOrigin, fScaling, rChar2Base, rGlyph2Char, rCharDxs, rDXOffset, bBaseGlyph);
-+            bBaseGlyph = false;
-+        }
-+    }
-+    // from the point of view of the dx array, the xpos is
-+    // the origin of the first glyph of the next cluster ltr
-+    // rtl it is the origin of the 1st glyph of the cluster
-+    long nXPos = (bRtl)?
-+        round(aFirstGlyph.attachedClusterBase()->origin() * fScaling) + rDXOffset :
-+        round(aBounds.second * fScaling) + rDXOffset;
-+    // force the last char in range to have the width of the cluster
-+//     for (int n = nNextChar - nDelta; n != nFirstCharInCluster - nDelta; n-= nDelta)
-+//     {
-+//         if (nNextChar-nDelta < rArgs.mnEndCharPos && nNextChar-nDelta >= rArgs.mnMinCharPos)
-+//             rCharDxs[nNextChar-nDelta-rArgs.mnMinCharPos] = nXPos;
-+//     }
-+    if (bRtl)
-+    {
-+        for (int n = nNextChar + 1; n <= nFirstCharInCluster; n++)
-+        {
-+            if ((n < rArgs.mnEndCharPos) && (n >= rArgs.mnMinCharPos))
-+                rCharDxs[n-rArgs.mnMinCharPos] = nXPos;
-+        }
-+    }
-+    else
-+    {
-+        for (int n = nNextChar - 1; n >= nFirstCharInCluster; n--)
-+        {
-+            if (n < rArgs.mnEndCharPos && n >= rArgs.mnMinCharPos)
-+                rCharDxs[n-rArgs.mnMinCharPos] = nXPos;
-+        }
-+    }
-+#ifdef GRLAYOUT_DEBUG
-+    fprintf(grLog(),"Cluster g[%d-%d) c[%d-%d)%x x%ld y%f\n", nFirstGlyphInCluster, nNextGlyph, nFirstCharInCluster, nNextChar, rArgs.mpStr[nFirstCharInCluster], nXPos, aFirstGlyph.yOffset());
-+#endif
-+    return aBounds;
-+}
-+
-+// append walks an attachment tree, flattening it, and converting it into a
-+// sequence of GlyphItem objects which we can later manipulate.
-+void
-+GraphiteLayout::Glyphs::append(gr::Segment &segment, ImplLayoutArgs &args, gr::GlyphInfo & gi, float nextGlyphOrigin, float scaling, std::vector<int> & rChar2Base, std::vector<int> & rGlyph2Char, std::vector<int> & rCharDxs, long & rDXOffset, bool bIsBase)
-+{
-+    float nextOrigin = nextGlyphOrigin;
-+    int firstChar = std::min(gi.firstChar(), gi.lastChar());
-+    assert(size() < rGlyph2Char.size());
-+    if (!bIsBase) rGlyph2Char[size()] = firstChar;
-+    // is the next glyph attached or in the next cluster?
-+    glyph_set_range_t iAttached = gi.attachedClusterGlyphs();
-+    if (iAttached.first != iAttached.second)
-+    {
-+        nextOrigin = iAttached.first->origin();
-+    }
-+    long glyphId = gi.glyphID();
-+    long deltaOffset = 0;
-+    int glyphWidth = round(nextOrigin * scaling) - round(gi.origin() * scaling);
-+#ifdef GRLAYOUT_DEBUG
-+    fprintf(grLog(),"c%d g%d gWidth%d x%f ", firstChar, (int)gi.logicalIndex(), glyphWidth, nextOrigin);
-+#endif
-+    if (glyphId == 0)
-+    {
-+        args.NeedFallback(
-+            firstChar,
-+            gr::RightToLeftDir(gr::DirCode(gi.directionality())));
-+        if( (SAL_LAYOUT_FOR_FALLBACK & args.mnFlags ))
-+        {
-+            glyphId = GF_DROPPED;
-+            deltaOffset -= glyphWidth;
-+            glyphWidth = 0;
-+        }
-+    }
-+    else if(args.mnFlags & SAL_LAYOUT_FOR_FALLBACK)
-+    {
-+#ifdef GRLAYOUT_DEBUG
-+        fprintf(grLog(),"fallback c%d %x in run %d\n", firstChar, args.mpStr[firstChar],
-+            args.maRuns.PosIsInAnyRun(firstChar));
-+#endif
-+        // glyphs that aren't requested for fallback will be taken from base
-+        // layout, so mark them as dropped (should this wait until Simplify(false) is called?)
-+        if (!args.maRuns.PosIsInAnyRun(firstChar) &&
-+            in_range(firstChar, args.mnMinCharPos, args.mnEndCharPos))
-+        {
-+            glyphId = GF_DROPPED;
-+            deltaOffset -= glyphWidth;
-+            glyphWidth = 0;
-+        }
-+    }
-+    // append this glyph.
-+    long nGlyphFlags = bIsBase ? 0 : GlyphItem::IS_IN_CLUSTER;
-+    nGlyphFlags |= gr::RightToLeftDir(gr::DirCode(gi.directionality())) ? GlyphItem::IS_RTL_GLYPH : 0;
-+    GlyphItem aGlyphItem(size(),//gi.logicalIndex(),
-+        glyphId,
-+        Point(round(gi.origin() * scaling + rDXOffset),
-+            round((-gi.yOffset() * scaling) - segment.AscentOffset()* scaling)),
-+        nGlyphFlags,
-+        glyphWidth);
-+    aGlyphItem.mnOrigWidth = round(gi.advanceWidth() * scaling);
-+    push_back(aGlyphItem);
-+
-+    // update the offset if this glyph was dropped
-+    rDXOffset += deltaOffset;
-+
-+    // Recursively apply append all the attched glyphs.
-+    for (gr::GlyphSetIterator agi = iAttached.first; agi != iAttached.second; ++agi)
-+    {
-+        if (agi + 1 == iAttached.second)
-+            append(segment, args, *agi, nextGlyphOrigin, scaling, rChar2Base, rGlyph2Char,rCharDxs, rDXOffset, false);
-+        else
-+            append(segment, args, *agi, (agi + 1)->origin(), scaling, rChar2Base, rGlyph2Char, rCharDxs, rDXOffset, false);
-+    }
-+}
-+
-+//
-+// An implementation of the SalLayout interface to enable Graphite enabled fonts to be used.
-+//
-+GraphiteLayout::GraphiteLayout(const gr::Font & font, const grutils::GrFeatureParser * pFeatures) throw()
-+  : mpTextSrc(0),
-+    mrFont(font),
-+    mnWidth(0),
-+    mfScaling(1.0),
-+    mpFeatures(pFeatures)
-+{
-+    // Line settings can have subtle affects on space handling
-+    // since we don't really know whether it is the end of a line or just a run
-+    // in the middle, it is hard to know what to set them to.
-+    // If true, it can cause end of line spaces to be hidden e.g. Doulos SIL
-+    maLayout.setStartOfLine(false);
-+    maLayout.setEndOfLine(false);
-+//    maLayout.setDumbFallback(false);
-+    // trailing ws doesn't seem to always take affect if end of line is true
-+    maLayout.setTrailingWs(gr::ktwshAll);
-+#ifdef GRLAYOUT_DEBUG
-+    gr::ScriptDirCode aDirCode = font.getSupportedScriptDirections();
-+    fprintf(grLog(),"GraphiteLayout scripts %x %lx\n", aDirCode, long(this));
-+#endif
-+}
-+
-+
-+GraphiteLayout::~GraphiteLayout() throw()
-+{
-+    clear();
-+    // the features are owned by the platform layers
-+    mpFeatures = NULL;
-+}
-+
-+void GraphiteLayout::clear()
-+{
-+    // Destroy the segment and text source from any previous invocation of
-+    // LayoutText
-+    mvGlyphs.clear();
-+    mvCharDxs.clear();
-+    mvChar2BaseGlyph.clear();
-+    mvGlyph2Char.clear();
-+
-+#ifndef GRCACHE
-+    delete mpTextSrc;
-+#endif
-+
-+    // Reset the state to the empty state.
-+    mpTextSrc=0;
-+    mnWidth = 0;
-+    // Don't reset the scaling, because it is set before LayoutText
-+}
-+
-+// This method shouldn't be called on windows, since it needs the dc reset
-+bool GraphiteLayout::LayoutText(ImplLayoutArgs & rArgs)
-+{
-+#ifdef GRCACHE
-+    GrSegRecord * pSegRecord = NULL;
-+    gr::Segment * pSegment = CreateSegment(rArgs, &pSegRecord);
-+    if (!pSegment)
-+       return false;
-+
-+    // layout the glyphs as required by OpenOffice
-+    bool success = LayoutGlyphs(rArgs, pSegment, pSegRecord);
-+
-+    if (pSegRecord) pSegRecord->unlock();
-+    else delete pSegment;
-+#else
-+    gr::Segment * pSegment = CreateSegment(rArgs);
-+    bool success = LayoutGlyphs(rArgs, pSegment);
-+    delete pSegment;
-+#endif
-+    return success;
-+}
-+
-+#ifdef GRCACHE
-+class GrFontHasher : public gr::Font
-+{
-+public:
-+    GrFontHasher(const gr::Font & aFont) : gr::Font(aFont), mrRealFont(const_cast<gr::Font&>(aFont)) {};
-+    ~GrFontHasher(){};
-+    virtual bool bold() { return mrRealFont.bold(); };
-+    virtual bool italic() { return mrRealFont.italic(); };
-+    virtual float ascent()  { return mrRealFont.ascent(); };
-+    virtual float descent()  { return mrRealFont.descent(); };
-+    virtual float height()  { return mrRealFont.height(); };
-+    virtual gr::Font* copyThis() { return mrRealFont.copyThis(); };
-+    virtual unsigned int getDPIx() { return mrRealFont.getDPIx(); };
-+    virtual unsigned int getDPIy() { return mrRealFont.getDPIy(); };
-+    virtual const void* getTable(gr::fontTableId32 nId, size_t* nSize)
-+    { return mrRealFont.getTable(nId,nSize); }
-+    virtual void getFontMetrics(float*pA, float*pB, float*pC) { mrRealFont.getFontMetrics(pA,pB,pC); };
-+
-+    sal_Int32 hashCode(const grutils::GrFeatureParser * mpFeatures)
-+    {
-+        // is this sufficient?
-+        std::wstring aFace;
-+        bool bBold;
-+        bool bItalic;
-+        UniqueCacheInfo(aFace, bBold, bItalic);
-+        sal_Unicode uName[32]; // max length used in gr::Font
-+        // Note: graphite stores font names as UTF-16 even if wchar_t is 32bit
-+        // this conversion should be OK.
-+        for (size_t i = 0; i < aFace.size() && i < 32; i++)
-+        {
-+            uName[i] = aFace[i];
-+        }
-+        size_t iSize = aFace.size();
-+        if (0 == iSize) return 0;
-+        sal_Int32 hash = rtl_ustr_hashCode_WithLength(uName, iSize);
-+        hash ^= static_cast<sal_Int32>(height());
-+        hash |= (bBold)? 0x1000000 : 0;
-+        hash |= (bItalic)? 0x2000000 : 0;
-+        if (mpFeatures)
-+            hash ^= mpFeatures->hashCode();
-+#ifdef GRLAYOUT_DEBUG
-+        fprintf(grLog(), "font hash %x size %f\n", hash, height());
-+#endif
-+        return hash;
-+    };
-+
-+private:
-+    gr::Font & mrRealFont;
-+};
-+#endif
-+
-+#ifdef GRCACHE
-+gr::Segment * GraphiteLayout::CreateSegment(ImplLayoutArgs& rArgs, GrSegRecord ** pSegRecord)
-+#else
-+gr::Segment * GraphiteLayout::CreateSegment(ImplLayoutArgs& rArgs)
-+#endif
-+{
-+    assert(rArgs.mnLength >= 0);
-+
-+    gr::Segment * pSegment = NULL;
-+
-+    // Set the SalLayouts values to be the inital ones.
-+    SalLayout::AdjustLayout(rArgs);
-+    // TODO check if this is needed
-+    if (mnUnitsPerPixel > 1)
-+        mfScaling = 1.0f / mnUnitsPerPixel;
-+
-+    // Clear out any previous buffers
-+    clear();
-+    bool bRtl = mnLayoutFlags & SAL_LAYOUT_BIDI_RTL;
-+    try
-+    {
-+        // Don't set RTL if font doesn't support it otherwise it forces rtl on
-+        // everything
-+        if (bRtl && (mrFont.getSupportedScriptDirections() & gr::kfsdcHorizRtl))
-+            maLayout.setRightToLeft(bRtl);
-+
-+#ifdef GRCACHE
-+        GrFontHasher hasher(mrFont);
-+        sal_Int32 aFontHash = hasher.hashCode(mpFeatures);
-+        GraphiteSegmentCache * pCache =
-+            (GraphiteCacheHandler::instance).getCache(aFontHash);
-+        if (pCache)
-+        {
-+            *pSegRecord = pCache->getSegment(rArgs, bRtl);
-+            if (*pSegRecord)
-+            {
-+                pSegment = (*pSegRecord)->getSegment();
-+                mpTextSrc = (*pSegRecord)->getTextSrc();
-+                maLayout.setRightToLeft((*pSegRecord)->isRtl());
-+                if (rArgs.mpStr != mpTextSrc->getLayoutArgs().mpStr ||
-+                    rArgs.mnMinCharPos != mpTextSrc->getLayoutArgs().mnMinCharPos ||
-+                    rArgs.mnEndCharPos != mpTextSrc->getLayoutArgs().mnEndCharPos ||
-+                    (SAL_LAYOUT_FOR_FALLBACK & rArgs.mnFlags) )
-+                {
-+                    (*pSegRecord)->clearVectors();
-+                }
-+                mpTextSrc->switchLayoutArgs(rArgs);
-+                return pSegment;
-+            }
-+        }
-+#endif
-+
-+        // Context is often needed beyond the specified end, however, we don't
-+        // want it if there has been a direction change, since it is hard
-+        // to tell between reordering within one direction and multi-directional
-+        // text.
-+        const int  segCharLimit = min(rArgs.mnLength, mnEndCharPos + EXTRA_CONTEXT_LENGTH);
-+        int limit = rArgs.mnEndCharPos;
-+        if (segCharLimit > limit)
-+        {
-+            limit += findSameDirLimit(rArgs.mpStr + rArgs.mnEndCharPos,
-+                segCharLimit - rArgs.mnEndCharPos, bRtl);
-+        }
-+
-+        // Create a new TextSource object for the engine.
-+        mpTextSrc = new TextSourceAdaptor(rArgs, limit);
-+        if (mpFeatures) mpTextSrc->setFeatures(mpFeatures);
-+
-+        pSegment = new gr::RangeSegment((gr::Font *)&mrFont, mpTextSrc, &maLayout, mnMinCharPos, limit);
-+        if (pSegment != NULL)
-+        {
-+#ifdef GRLAYOUT_DEBUG
-+            fprintf(grLog(),"Gr::LayoutText %d-%d, context %d,len%d rtl%d/%d scaling %f\n", rArgs.mnMinCharPos,
-+               rArgs.mnEndCharPos, limit, rArgs.mnLength, maLayout.rightToLeft(), pSegment->rightToLeft(), mfScaling);
-+#endif
-+#ifdef GRCACHE
-+            // on a new segment rightToLeft should be correct
-+            *pSegRecord = pCache->cacheSegment(mpTextSrc, pSegment, pSegment->rightToLeft());
-+#endif
-+        }
-+        else
-+        {
-+            clear();
-+            return NULL;
-+        }
-+    }
-+    catch (...)
-+    {
-+        clear();  // destroy the text source and any partially built segments.
-+        return NULL;
-+    }
-+    return pSegment;
-+}
-+
-+#ifdef GRCACHE
-+bool GraphiteLayout::LayoutGlyphs(ImplLayoutArgs& rArgs, gr::Segment * pSegment, GrSegRecord * pSegRecord)
-+#else
-+bool GraphiteLayout::LayoutGlyphs(ImplLayoutArgs& rArgs, gr::Segment * pSegment)
-+#endif
-+{
-+#ifdef GRCACHE
-+#ifdef GRCACHE_REUSE_VECTORS
-+    // if we have an exact match, then we can reuse the glyph vectors from before
-+    if (pSegRecord && (pSegRecord->glyphs().size() > 0) &&
-+        !(SAL_LAYOUT_FOR_FALLBACK & rArgs.mnFlags) )
-+    {
-+        mnWidth = pSegRecord->width();
-+        mvGlyphs = pSegRecord->glyphs();
-+        mvCharDxs = pSegRecord->charDxs();
-+        mvChar2BaseGlyph = pSegRecord->char2BaseGlyph();
-+        mvGlyph2Char = pSegRecord->glyph2Char();
-+        return true;
-+    }
-+#endif
-+#endif
-+    // Calculate the initial character dxs.
-+    mvCharDxs.assign(mnEndCharPos - mnMinCharPos, -1);
-+    mvChar2BaseGlyph.assign(mnEndCharPos - mnMinCharPos, -1);
-+    mnWidth = 0;
-+    if (mvCharDxs.size() > 0)
-+    {
-+        // Discover all the clusters.
-+        try
-+        {
-+            // Note: we use the layout rightToLeft() because in cached segments
-+            // rightToLeft() may no longer be valid if the engine has been run
-+            // ltr since the segment was created.
-+#ifdef GRCACHE
-+			bool bRtl = pSegRecord? pSegRecord->isRtl() : pSegment->rightToLeft();
-+#else
-+			bool bRtl = pSegment->rightToLeft();
-+#endif
-+            mvGlyphs.fill_from(*pSegment, rArgs, bRtl,
-+                mnWidth, mfScaling, mvChar2BaseGlyph, mvGlyph2Char, mvCharDxs);
-+
-+            if (bRtl)
-+            {
-+                // not needed for adjacent differences, but for mouse clicks to char
-+                std::transform(mvCharDxs.begin(), mvCharDxs.end(), mvCharDxs.begin(),
-+                    std::bind1st(std::minus<long>(), mnWidth));
-+                // fixup last dx to ensure it always equals the width
-+                mvCharDxs[mvCharDxs.size() - 1] = mnWidth;
-+            }
-+#ifdef GRCACHE
-+#ifdef GRCACHE_REUSE_VECTORS
-+            if (pSegRecord && rArgs.maReruns.IsEmpty() &&
-+                !(SAL_LAYOUT_FOR_FALLBACK & rArgs.mnFlags))
-+            {
-+                pSegRecord->setGlyphVectors(mnWidth, mvGlyphs, mvCharDxs,
-+                                            mvChar2BaseGlyph, mvGlyph2Char);
-+            }
-+#endif
-+#endif
-+        }
-+        catch (std::exception e)
-+        {
-+#ifdef GRLAYOUT_DEBUG
-+            fprintf(grLog(),"LayoutGlyphs failed %s\n", e.what());
-+#endif
-+            return false;
-+        }
-+        catch (...)
-+        {
-+#ifdef GRLAYOUT_DEBUG
-+            fprintf(grLog(),"LayoutGlyphs failed with exception");
-+#endif
-+            return false;
-+        }
-+	}
-+    else
-+    {
-+        mnWidth = 0;
-+    }
-+    return true;
-+}
-+
-+int GraphiteLayout::GetTextBreak(long maxmnWidth, long char_extra, int factor) const
-+{
-+    // Adjust maxmnWidth so FindNextBreakPoint returns a sensible answer.
-+    maxmnWidth -= (mnEndCharPos-mnMinCharPos-1)*char_extra;  // extra character spacing.
-+    maxmnWidth /= factor;                                    // scaling factor.
-+
-+    // Ask the segment for the nearest whole letter break for the width.
-+    //float width;
-+    float targetWidth = maxmnWidth/mfScaling;
-+    // return quickly if this segment is narrower than the target width
-+    // (sometimes graphite doesn't seem to realise this!)
-+    if (targetWidth > mnWidth)
-+        return STRING_LEN;
-+    //int    nBreak = mpSegment->findNextBreakPoint(mnMinCharPos,
-+    //        gr::klbWordBreak, gr::klbLetterBreak, targetWidth, &width);
-+
-+    // LineFillSegment seems to give better results that findNextBreakPoint
-+    // though it may be slower
-+    gr::LayoutEnvironment aLE;
-+    gr::LineFillSegment lineSeg(const_cast<gr::Font *>(&mrFont), mpTextSrc, &aLE,
-+                                mnMinCharPos, mpTextSrc->getContextLength(),
-+                                targetWidth);
-+    int nBreak = lineSeg.stopCharacter();
-+
-+    if (nBreak > mnEndCharPos) nBreak = STRING_LEN;
-+    else if (nBreak < mnMinCharPos) nBreak = mnMinCharPos;
-+    return nBreak;
-+}
-+
-+
-+long GraphiteLayout::FillDXArray( sal_Int32* pDXArray ) const
-+{
-+    if (mnEndCharPos == mnMinCharPos)
-+        // Then we must be zero width!
-+        return 0;
-+
-+    if (pDXArray)
-+    {
-+        for (size_t i = 0; i < mvCharDxs.size(); i++)
-+        {
-+            assert((mvChar2BaseGlyph[i] >= -1) && (mvChar2BaseGlyph[i] < (signed)mvGlyphs.size()));
-+            if (mvChar2BaseGlyph[i] != -1 &&
-+                mvGlyphs[mvChar2BaseGlyph[i]].mnGlyphIndex == GF_DROPPED)
-+            {
-+                // when used in MultiSalLayout::GetTextBreak dropped glyphs
-+                // must have zero width
-+                pDXArray[i] = 0;
-+            }
-+            else
-+            {
-+                pDXArray[i] = mvCharDxs[i];
-+                if (i > 0) pDXArray[i] -= mvCharDxs[i-1];
-+            }
-+#ifdef GRLAYOUT_DEBUG
-+            fprintf(grLog(),"%d,%d,%d ", (int)i, (int)mvCharDxs[i], pDXArray[i]);
-+#endif
-+        }
-+        //std::adjacent_difference(mvCharDxs.begin(), mvCharDxs.end(), pDXArray);
-+        //for (size_t i = 0; i < mvCharDxs.size(); i++)
-+        //    fprintf(grLog(),"%d,%d,%d ", (int)i, (int)mvCharDxs[i], pDXArray[i]);
-+        //fprintf(grLog(),"FillDX %ld,%d\n", mnWidth, std::accumulate(pDXArray, pDXArray + mvCharDxs.size(), 0));
-+    }
-+#ifdef GRLAYOUT_DEBUG
-+    fprintf(grLog(),"FillDXArray %d-%d,%d=%ld\n", mnMinCharPos, mnEndCharPos, (int)mpTextSrc->getLength(), mnWidth);
-+#endif
-+    return mnWidth;
-+}
-+
-+
-+void  GraphiteLayout::AdjustLayout(ImplLayoutArgs& args)
-+{
-+    SalLayout::AdjustLayout(args);
-+
-+    if(args.mpDXArray)
-+        ApplyDXArray(args);
-+//    else if( rArgs.mnLayoutWidth )  FIXME: Justification
-+//        Justify( rArgs.mnLayoutWidth );
-+}
-+
-+
-+void GraphiteLayout::ApplyDXArray(ImplLayoutArgs &args)
-+{
-+    const size_t nChars = args.mnEndCharPos - args.mnMinCharPos;
-+    if (nChars == 0) return;
-+
-+#ifdef GRLAYOUT_DEBUG
-+    for (size_t iDx = 0; iDx < mvCharDxs.size(); iDx++)
-+         fprintf(grLog(),"%d,%d,%d ", (int)iDx, (int)mvCharDxs[iDx], args.mpDXArray[iDx]);
-+    fprintf(grLog(),"ApplyDx\n");
-+#endif
-+    bool bRtl = mnLayoutFlags & SAL_LAYOUT_BIDI_RTL;
-+    int nXOffset = 0;
-+    if (bRtl)
-+    {
-+        nXOffset = args.mpDXArray[nChars - 1] - mvCharDxs[nChars - 1];
-+    }
-+    int nPrevClusterGlyph = (bRtl)? mvGlyphs.size() : -1;
-+    int nPrevClusterLastChar = -1;
-+    for (size_t i = 0; i < nChars; i++)
-+    {
-+        if (mvChar2BaseGlyph[i] > -1 && mvChar2BaseGlyph[i] != nPrevClusterGlyph)
-+        {
-+            assert((mvChar2BaseGlyph[i] > -1) && (mvChar2BaseGlyph[i] < (signed)mvGlyphs.size()));
-+            GlyphItem & gi = mvGlyphs[mvChar2BaseGlyph[i]];
-+            if (!gi.IsClusterStart())
-+                continue;
-+
-+            // find last glyph of this cluster
-+            size_t j = i + 1;
-+            int nLastChar = i;
-+            int nLastGlyph = mvChar2BaseGlyph[i];
-+            for (; j < nChars; j++)
-+            {
-+                assert((mvChar2BaseGlyph[j] >= -1) && (mvChar2BaseGlyph[j] < (signed)mvGlyphs.size()));
-+                if (mvChar2BaseGlyph[j] != -1 && mvGlyphs[mvChar2BaseGlyph[j]].IsClusterStart())
-+                {
-+                    nLastGlyph = mvChar2BaseGlyph[j] + ((bRtl)? 1 : -1);
-+                    nLastChar = j - 1;
-+                    break;
-+                }
-+            }
-+            // Its harder to find the last glyph rtl, since the first of
-+            // cluster is still on the left so we need to search towards
-+            // the previous cluster to the right
-+            if (bRtl)
-+            {
-+                nLastGlyph = mvChar2BaseGlyph[i];
-+                while (nLastGlyph + 1 < (signed)mvGlyphs.size() &&
-+                       !mvGlyphs[nLastGlyph+1].IsClusterStart())
-+                {
-+                    ++nLastGlyph;
-+                }
-+            }
-+            if (j == nChars)
-+            {
-+                nLastChar = nChars - 1;
-+                if (!bRtl) nLastGlyph = mvGlyphs.size() - 1;
-+            }
-+            assert((nLastChar > -1) && (nLastChar < (signed)nChars));
-+            long nNewClusterWidth = args.mpDXArray[nLastChar];
-+            long nOrigClusterWidth = mvCharDxs[nLastChar];
-+            long nDGlyphOrigin = 0;
-+            if (nPrevClusterLastChar > - 1)
-+            {
-+                assert(nPrevClusterLastChar < (signed)nChars);
-+                nNewClusterWidth -= args.mpDXArray[nPrevClusterLastChar];
-+                nOrigClusterWidth -= mvCharDxs[nPrevClusterLastChar];
-+                nDGlyphOrigin = args.mpDXArray[nPrevClusterLastChar] - mvCharDxs[nPrevClusterLastChar];
-+            }
-+            long nDWidth = nNewClusterWidth - nOrigClusterWidth;
-+            assert((nLastGlyph > -1) && (nLastGlyph < (signed)mvGlyphs.size()));
-+            mvGlyphs[nLastGlyph].mnNewWidth += nDWidth;
-+            if (gi.mnGlyphIndex != GF_DROPPED)
-+                mvGlyphs[nLastGlyph].mnNewWidth += nDWidth;
-+            else
-+                nDGlyphOrigin += nDWidth;
-+            // update glyph positions
-+            if (bRtl)
-+            {
-+                for (int n = mvChar2BaseGlyph[i]; n <= nLastGlyph; n++)
-+                {
-+                    assert((n > - 1) && (n < (signed)mvGlyphs.size()));
-+                    mvGlyphs[n].maLinearPos.X() += -nDGlyphOrigin + nXOffset;
-+                }
-+            }
-+            else
-+            {
-+                for (int n = mvChar2BaseGlyph[i]; n <= nLastGlyph; n++)
-+                {
-+                    assert((n > - 1) && (n < (signed)mvGlyphs.size()));
-+                    mvGlyphs[n].maLinearPos.X() += nDGlyphOrigin + nXOffset;
-+                }
-+            }
-+#ifdef GRLAYOUT_DEBUG
-+            fprintf(grLog(),"c%d g%d-%d dW%ld-%ld=%ld dX%ld x%ld\t", (int)i, mvChar2BaseGlyph[i], nLastGlyph, nNewClusterWidth, nOrigClusterWidth, nDWidth, nDGlyphOrigin, mvGlyphs[mvChar2BaseGlyph[i]].maLinearPos.X());
-+#endif
-+            nPrevClusterGlyph = mvChar2BaseGlyph[i];
-+            nPrevClusterLastChar = nLastChar;
-+            i = nLastChar;
-+        }
-+    }
-+    // Update the dx vector with the new values.
-+    std::copy(args.mpDXArray, args.mpDXArray + nChars,
-+      mvCharDxs.begin() + (args.mnMinCharPos - mnMinCharPos));
-+#ifdef GRLAYOUT_DEBUG
-+    fprintf(grLog(),"ApplyDx %d(%ld)\n", args.mpDXArray[nChars - 1], mnWidth);
-+#endif
-+    mnWidth = args.mpDXArray[nChars - 1];
-+}
-+
-+
-+void GraphiteLayout::GetCaretPositions( int nArraySize, sal_Int32* pCaretXArray ) const
-+{
-+    // For each character except the last discover the caret positions
-+    // immediatly before and after that character.
-+    // This is used for underlines in the GUI amongst other things.
-+    // It may be used from MultiSalLayout, in which case it must take into account
-+    // glyphs that have been moved.
-+    std::fill(pCaretXArray, pCaretXArray + nArraySize, -1);
-+    // the layout method doesn't modify the layout even though it isn't
-+    // const in the interface
-+    bool bRtl = const_cast<GraphiteLayout*>(this)->maLayout.rightToLeft();
-+    int prevBase = -1;
-+    long prevClusterWidth = 0;
-+    for (int i = 0, nCharSlot = 0; i < nArraySize && nCharSlot < static_cast<int>(mvCharDxs.size()); ++nCharSlot, i+=2)
-+    {
-+        if (mvChar2BaseGlyph[nCharSlot] != -1)
-+        {
-+            assert((mvChar2BaseGlyph[nCharSlot] > -1) && (mvChar2BaseGlyph[nCharSlot] < (signed)mvGlyphs.size()));
-+            GlyphItem gi = mvGlyphs[mvChar2BaseGlyph[nCharSlot]];
-+            if (gi.mnGlyphIndex == GF_DROPPED)
-+            {
-+                continue;
-+            }
-+            int nCluster = mvChar2BaseGlyph[nCharSlot];
-+            long origClusterWidth = gi.mnNewWidth;
-+            long nMin = gi.maLinearPos.X();
-+            long nMax = gi.maLinearPos.X() + gi.mnNewWidth;
-+            // attached glyphs are always stored after their base rtl or ltr
-+            while (++nCluster < static_cast<int>(mvGlyphs.size()) &&
-+                !mvGlyphs[nCluster].IsClusterStart())
-+            {
-+                origClusterWidth += mvGlyphs[nCluster].mnNewWidth;
-+                if (mvGlyph2Char[nCluster] == nCharSlot)
-+                {
-+                    nMin = std::min(nMin, mvGlyphs[nCluster].maLinearPos.X());
-+                    nMax = std::min(nMax, mvGlyphs[nCluster].maLinearPos.X() + mvGlyphs[nCluster].mnNewWidth);
-+                }
-+            }
-+            if (bRtl)
-+            {
-+                pCaretXArray[i+1] = nMin;
-+                pCaretXArray[i] = nMax;
-+            }
-+            else
-+            {
-+                pCaretXArray[i] = nMin;
-+                pCaretXArray[i+1] = nMax;
-+            }
-+            prevBase = mvChar2BaseGlyph[nCharSlot];
-+            prevClusterWidth = origClusterWidth;
-+        }
-+        else if (prevBase > -1)
-+        {
-+            // this could probably be improved
-+            assert((prevBase > -1) && (prevBase < (signed)mvGlyphs.size()));
-+            GlyphItem gi = mvGlyphs[prevBase];
-+            int nGlyph = prevBase + 1;
-+            // try to find a better match, otherwise default to complete cluster
-+            for (; nGlyph < static_cast<int>(mvGlyphs.size()) &&
-+                 !mvGlyphs[nGlyph].IsClusterStart(); nGlyph++)
-+            {
-+                if (mvGlyph2Char[nGlyph] == nCharSlot)
-+                {
-+                    gi = mvGlyphs[nGlyph];
-+                    break;
-+                }
-+            }
-+            long nGWidth = gi.mnNewWidth;
-+            // if no match position at end of cluster
-+            if (nGlyph == static_cast<int>(mvGlyphs.size()) ||
-+                mvGlyphs[nGlyph].IsClusterStart())
-+            {
-+                nGWidth = prevClusterWidth;
-+                if (bRtl)
-+                {
-+                    pCaretXArray[i+1] = gi.maLinearPos.X();
-+                    pCaretXArray[i] = gi.maLinearPos.X();
-+                }
-+                else
-+                {
-+                    pCaretXArray[i] = gi.maLinearPos.X() + prevClusterWidth;
-+                    pCaretXArray[i+1] = gi.maLinearPos.X() + prevClusterWidth;
-+                }
-+            }
-+            else
-+            {
-+                if (bRtl)
-+                {
-+                    pCaretXArray[i+1] = gi.maLinearPos.X();
-+                    pCaretXArray[i] = gi.maLinearPos.X() + gi.mnNewWidth;
-+                }
-+                else
-+                {
-+                    pCaretXArray[i] = gi.maLinearPos.X();
-+                    pCaretXArray[i+1] = gi.maLinearPos.X() + gi.mnNewWidth;
-+                }
-+            }
-+        }
-+        else
-+        {
-+            pCaretXArray[i] = pCaretXArray[i+1] = 0;
-+        }
-+#ifdef GRLAYOUT_DEBUG
-+        fprintf(grLog(),"%d,%d-%d\t", nCharSlot, pCaretXArray[i], pCaretXArray[i+1]);
-+#endif
-+    }
-+#ifdef GRLAYOUT_DEBUG
-+    fprintf(grLog(),"\n");
-+#endif
-+}
-+
-+
-+// GetNextGlyphs returns a contiguous sequence of glyphs that can be
-+// rendered together. It should never return a dropped glyph.
-+// The glyph_slot returned should be the index of the next visible
-+// glyph after the last glyph returned by this call.
-+// The char_index array should be filled with the characters corresponding
-+// to each glyph returned.
-+// glyph_adv array should be a virtual width such that if successive
-+// glyphs returned by this method are added one after the other they
-+// have the correct spacing.
-+// The logic in this method must match that expected in MultiSalLayout which
-+// is used when glyph fallback is in operation.
-+int GraphiteLayout::GetNextGlyphs( int length, sal_GlyphId * glyph_out,
-+        ::Point & aPosOut, int &glyph_slot, sal_Int32 * glyph_adv, int *char_index) const
-+{
-+  // Sanity check on the slot index.
-+  if (glyph_slot >= signed(mvGlyphs.size()))
-+  {
-+    glyph_slot = mvGlyphs.size();
-+    return 0;
-+  }
-+  assert(glyph_slot >= 0);
-+  // Find the first glyph in the substring.
-+  for (; glyph_slot < signed(mvGlyphs.size()) &&
-+          ((mvGlyphs.begin() + glyph_slot)->mnGlyphIndex == GF_DROPPED);
-+          ++glyph_slot) {};
-+
-+  // Update the length
-+  const int nGlyphSlotEnd = std::min(size_t(glyph_slot + length), mvGlyphs.size());
-+
-+  // We're all out of glyphs here.
-+  if (glyph_slot == nGlyphSlotEnd)
-+  {
-+    return 0;
-+  }
-+
-+  // Find as many glyphs as we can which can be drawn in one go.
-+  Glyphs::const_iterator glyph_itr = mvGlyphs.begin() + glyph_slot;
-+  const int         glyph_slot_begin = glyph_slot;
-+  const int            initial_y_pos = glyph_itr->maLinearPos.Y();
-+
-+  // Set the position to the position of the start glyph.
-+  ::Point aStartPos = glyph_itr->maLinearPos;
-+  //aPosOut = glyph_itr->maLinearPos;
-+  aPosOut = GetDrawPosition(aStartPos);
-+
-+
-+  for (;;)  // Forever
-+  {
-+     // last index of the range from glyph_to_chars does not include this glyph
-+     if (char_index)
-+     {
-+        assert((glyph_slot >= -1) && (glyph_slot < (signed)mvGlyph2Char.size()));
-+        if (mvGlyph2Char[glyph_slot] == -1)
-+            *char_index++ = mvCharDxs.size();
-+        else
-+            *char_index++ = mvGlyph2Char[glyph_slot];
-+     }
-+     // Copy out this glyphs data.
-+     ++glyph_slot;
-+     *glyph_out++ = glyph_itr->mnGlyphIndex;
-+
-+     // Find the actual advance - this must be correct if called from
-+     // MultiSalLayout::AdjustLayout which requests one glyph at a time.
-+     const long nGlyphAdvance = (glyph_slot == static_cast<int>(mvGlyphs.size()))?
-+          glyph_itr->mnNewWidth :
-+          ((glyph_itr+1)->maLinearPos.X() - glyph_itr->maLinearPos.X());
-+
-+#ifdef GRLAYOUT_DEBUG
-+    fprintf(grLog(),"GetNextGlyphs g%d c%d x%ld,%ld adv%ld, pos %ld,%ld\n", glyph_slot - 1,
-+            mvGlyph2Char[glyph_slot-1], glyph_itr->maLinearPos.X(), glyph_itr->maLinearPos.Y(), nGlyphAdvance,
-+            aPosOut.X(), aPosOut.Y());
-+#endif
-+
-+     if (glyph_adv)  // If we are returning advance store it.
-+       *glyph_adv++ = nGlyphAdvance;
-+     else // Stop when next advance is unexpected.
-+       if (glyph_itr->mnOrigWidth != nGlyphAdvance)  break;
-+
-+     // Have fetched all the glyphs we need to
-+     if (glyph_slot == nGlyphSlotEnd)
-+         break;
-+
-+     ++glyph_itr;
-+     // Stop when next y position is unexpected.
-+     if (initial_y_pos != glyph_itr->maLinearPos.Y())
-+       break;
-+
-+     // Stop if glyph dropped
-+     if (glyph_itr->mnGlyphIndex == GF_DROPPED)
-+       break;
-+  }
-+  int numGlyphs = glyph_slot - glyph_slot_begin;
-+  // move the next glyph_slot to a glyph that hasn't been dropped
-+  while (glyph_slot < static_cast<int>(mvGlyphs.size()) &&
-+         (mvGlyphs.begin() + glyph_slot)->mnGlyphIndex == GF_DROPPED)
-+         ++glyph_slot;
-+  return numGlyphs;
-+}
-+
-+
-+void GraphiteLayout::MoveGlyph( int nGlyphIndex, long nNewPos )
-+{
-+    // TODO it might be better to actualy implement simplify properly, but this
-+    // could needs to be done carefully so the glyph/char maps are maintained
-+    // If a glyph has been dropped then it wasn't returned by GetNextGlyphs, so
-+    // the index here may be wrong
-+    while ((mvGlyphs[nGlyphIndex].mnGlyphIndex == GF_DROPPED) &&
-+           (nGlyphIndex < (signed)mvGlyphs.size()))
-+    {
-+        nGlyphIndex++;
-+    }
-+    const long dx = nNewPos - mvGlyphs[nGlyphIndex].maLinearPos.X();
-+
-+    if (dx == 0)  return;
-+    // GenericSalLayout only changes maLinearPos, mvCharDxs doesn't change
-+#ifdef GRLAYOUT_DEBUG
-+    fprintf(grLog(),"Move %d (%ld,%ld) c%d by %ld\n", nGlyphIndex, mvGlyphs[nGlyphIndex].maLinearPos.X(), nNewPos, mvGlyph2Char[nGlyphIndex], dx);
-+#endif
-+    for (size_t gi = nGlyphIndex; gi < mvGlyphs.size(); gi++)
-+    {
-+        mvGlyphs[gi].maLinearPos.X() += dx;
-+    }
-+    // width does need to be updated for correct fallback
-+    mnWidth += dx;
-+}
-+
-+
-+void GraphiteLayout::DropGlyph( int nGlyphIndex )
-+{
-+    if(nGlyphIndex >= signed(mvGlyphs.size()))
-+        return;
-+
-+    GlyphItem & glyph = mvGlyphs[nGlyphIndex];
-+    glyph.mnGlyphIndex = GF_DROPPED;
-+#ifdef GRLAYOUT_DEBUG
-+    fprintf(grLog(),"Dropped %d\n", nGlyphIndex);
-+#endif
-+}
-+
-+void GraphiteLayout::Simplify( bool isBaseLayout )
-+{
-+  const sal_GlyphId dropMarker = isBaseLayout ? GF_DROPPED : 0;
-+
-+  Glyphs::iterator gi = mvGlyphs.begin();
-+  // TODO check whether we need to adjust positions here
-+  // MultiSalLayout seems to move the glyphs itself, so it may not be needed.
-+  long deltaX = 0;
-+  while (gi != mvGlyphs.end())
-+  {
-+      if (gi->mnGlyphIndex == dropMarker)
-+      {
-+        deltaX += gi->mnNewWidth;
-+        gi->mnNewWidth = 0;
-+      }
-+      else
-+      {
-+        deltaX = 0;
-+      }
-+      //mvCharDxs[mvGlyph2Char[gi->mnCharPos]] -= deltaX;
-+      ++gi;
-+  }
-+#ifdef GRLAYOUT_DEBUG
-+  fprintf(grLog(),"Simplify base%d dx=%ld newW=%ld\n", isBaseLayout, deltaX, mnWidth - deltaX);
-+#endif
-+  // discard width from trailing dropped glyphs, but not those in the middle
-+  mnWidth -= deltaX;
-+}
-Index: vcl/source/glyphs/graphite_serverfont.cxx
-===================================================================
---- vcl/source/glyphs/graphite_serverfont.cxx	(.../tags/DEV300_m35)	(Revision 0)
-+++ vcl/source/glyphs/graphite_serverfont.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,55 @@
-+//
-+// C++ Implementation: GraphiteLayout
-+//
-+// Description: An implementation of the SalLayout interface that use the
-+//              Graphite engine.
-+//
-+// Author: Tim Eves <tim_eves at sil.org>
-+//
-+// Copyright: Copyright (C) 2003 SIL International.
-+//            All rights reserved. Distributable under the terms of either
-+//            the Common Public License or the GNU Lesser General Public
-+//            License.
-+//
-+
-+// We need this to enable namespace support in libgrengine headers.
-+#define GR_NAMESPACE
-+
-+// Header files
-+//
-+
-+// Platform
-+#include <vcl/sallayout.hxx>
-+// Module
-+#include "gcach_ftyp.hxx"
-+#include <vcl/graphite_features.hxx>
-+#include "graphite_textsrc.hxx"
-+#include <vcl/graphite_serverfont.hxx>
-+
-+#ifndef MSC
-+
-+//
-+// An implementation of the GraphiteLayout interface to enable Graphite enabled fonts to be used.
-+//
-+
-+GraphiteServerFontLayout::GraphiteServerFontLayout(GraphiteFontAdaptor * pFont) throw()
-+  : ServerFontLayout(pFont->font()), mpFont(pFont),
-+    maImpl(*mpFont, mpFont->features())
-+{
-+    // Nothing needed here
-+}
-+
-+GraphiteServerFontLayout::~GraphiteServerFontLayout() throw()
-+{
-+    delete mpFont;
-+    mpFont = NULL;
-+}
-+
-+const sal_Unicode* GraphiteServerFontLayout::getTextPtr() const
-+{
-+    return maImpl.textSrc()->getLayoutArgs().mpStr +
-+        maImpl.textSrc()->getLayoutArgs().mnMinCharPos;
-+}
-+
-+
-+#endif
-Index: vcl/source/glyphs/graphite_features.cxx
-===================================================================
---- vcl/source/glyphs/graphite_features.cxx	(.../tags/DEV300_m35)	(Revision 0)
-+++ vcl/source/glyphs/graphite_features.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,268 @@
-+/*-----------------------------------------------------------------------------
-+Copyright (C) 2008 www.thanlwinsoft.org
-+
-+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:
-+Responsibility: Keith Stribley
-+Last reviewed: Not yet.
-+
-+Description:
-+Parse a string of features specified as ; separated pairs.
-+e.g.
-+1001=1;2002=2;fav1=0
-+
-+-----------------------------------------------------------------------------*/
-+
-+#include <sal/types.h>
-+
-+#ifdef MSC
-+#include <tools/svwin.h>
-+#include <svsys.h>
-+#endif
-+
-+#include <vcl/graphite_features.hxx>
-+
-+using namespace grutils;
-+// These mustn't conflict with font name lists which use ; and ,
-+const char GrFeatureParser::FEAT_PREFIX = ':';
-+const char GrFeatureParser::FEAT_SEPARATOR = '&';
-+const char GrFeatureParser::FEAT_ID_VALUE_SEPARATOR = '=';
-+const std::string GrFeatureParser::ISO_LANG("lang");
-+
-+GrFeatureParser::GrFeatureParser(gr::Font & font, const std::string lang)
-+    : mnNumSettings(0), mbErrors(false)
-+{
-+    maLang.rgch[0] = maLang.rgch[1] = maLang.rgch[2] = maLang.rgch[3] = '\0';
-+    setLang(font, lang);
-+}
-+
-+GrFeatureParser::GrFeatureParser(gr::Font & font, const std::string features, const std::string lang)
-+    : mnNumSettings(0), mbErrors(false)
-+{
-+    size_t nEquals = 0;
-+    size_t nFeatEnd = 0;
-+    size_t pos = 0;
-+    maLang.rgch[0] = maLang.rgch[1] = maLang.rgch[2] = maLang.rgch[3] = '\0';
-+    setLang(font, lang);
-+    while (pos < features.length() && mnNumSettings < MAX_FEATURES)
-+    {
-+        nEquals = features.find(FEAT_ID_VALUE_SEPARATOR,pos);
-+        if (nEquals == std::string::npos)
-+        {
-+            mbErrors = true;
-+            break;
-+        }
-+        // check for a lang=xxx specification
-+        if (features.compare(pos, nEquals - pos, ISO_LANG) == 0)
-+        {
-+            pos = nEquals + 1;
-+            nFeatEnd = features.find(FEAT_SEPARATOR, pos);
-+            if (nFeatEnd == std::string::npos)
-+            {
-+                nFeatEnd = features.length();
-+            }
-+            if (nFeatEnd - pos > 3)
-+                mbErrors = true;
-+            else
-+            {
-+                gr::isocode aLang = maLang;
-+                for (size_t i = pos; i < nFeatEnd; i++)
-+                    aLang.rgch[i-pos] = features[i];
-+                std::pair<gr::LanguageIterator,gr::LanguageIterator> aSupported
-+                    = font.getSupportedLanguages();
-+                gr::LanguageIterator iL = aSupported.first;
-+                while (iL != aSupported.second)
-+                {
-+                    gr::isocode aSupportedLang = *iL;
-+                    // here we only expect full 3 letter codes
-+                    if (aLang.rgch[0] == aSupportedLang.rgch[0] &&
-+                        aLang.rgch[1] == aSupportedLang.rgch[1] &&
-+                        aLang.rgch[2] == aSupportedLang.rgch[2] &&
-+                        aLang.rgch[3] == aSupportedLang.rgch[3]) break;
-+                    ++iL;
-+                }
-+                if (iL == aSupported.second) mbErrors = true;
-+                else maLang = aLang;
-+            }
-+        }
-+        else
-+        {
-+            if (isCharId(features, pos, nEquals - pos))
-+                maSettings[mnNumSettings].id = getCharId(features, pos, nEquals - pos);
-+            else maSettings[mnNumSettings].id = getIntValue(features, pos, nEquals - pos);
-+            pos = nEquals + 1;
-+            nFeatEnd = features.find(FEAT_SEPARATOR, pos);
-+            if (nFeatEnd == std::string::npos)
-+            {
-+                nFeatEnd = features.length();
-+            }
-+            if (isCharId(features, pos, nFeatEnd - pos))
-+                maSettings[mnNumSettings].value = getCharId(features, pos, nFeatEnd - pos);
-+            else
-+                maSettings[mnNumSettings].value= getIntValue(features, pos, nFeatEnd - pos);
-+            if (isValid(font, maSettings[mnNumSettings]))
-+                mnNumSettings++;
-+            else
-+                mbErrors = true;
-+        }
-+        pos = nFeatEnd + 1;
-+    }
-+}
-+
-+void GrFeatureParser::setLang(gr::Font & font, const std::string & lang)
-+{
-+    gr::isocode aLang = {{0,0,0,0}};
-+    if (lang.length() > 2)
-+    {
-+        for (size_t i = 0; i < lang.length() && i < 3; i++)
-+        {
-+            if (lang[i] == '-') break;
-+            aLang.rgch[i] = lang[i];
-+        }
-+        std::pair<gr::LanguageIterator,gr::LanguageIterator> aSupported
-+                    = font.getSupportedLanguages();
-+        gr::LanguageIterator iL = aSupported.first;
-+        while (iL != aSupported.second)
-+        {
-+            gr::isocode aSupportedLang = *iL;
-+            if (aLang.rgch[0] == aSupportedLang.rgch[0] &&
-+                aLang.rgch[1] == aSupportedLang.rgch[1] &&
-+                aLang.rgch[2] == aSupportedLang.rgch[2] &&
-+                aLang.rgch[3] == aSupportedLang.rgch[3]) break;
-+            ++iL;
-+        }
-+        if (iL != aSupported.second)
-+            maLang = aLang;
-+#ifdef DEBUG
-+        else
-+            printf("%s has no features\n", aLang.rgch);
-+#endif
-+    }
-+}
-+
-+GrFeatureParser::GrFeatureParser(const GrFeatureParser & aCopy)
-+ : maLang(aCopy.maLang), mbErrors(aCopy.mbErrors)
-+{
-+    mnNumSettings = aCopy.getFontFeatures(maSettings);
-+}
-+
-+GrFeatureParser::~GrFeatureParser()
-+{
-+}
-+
-+size_t GrFeatureParser::getFontFeatures(gr::FeatureSetting settings[64]) const
-+{
-+    if (settings)
-+    {
-+        std::copy(maSettings, maSettings + mnNumSettings, settings);
-+    }
-+    return mnNumSettings;
-+}
-+
-+bool GrFeatureParser::isValid(gr::Font & font, gr::FeatureSetting & setting)
-+{
-+    gr::FeatureIterator i = font.featureWithID(setting.id);
-+    if (font.getFeatures().second == i)
-+    {
-+        return false;
-+    }
-+    std::pair< gr::FeatureSettingIterator, gr::FeatureSettingIterator >
-+        validValues = font.getFeatureSettings(i);
-+    gr::FeatureSettingIterator j = validValues.first;
-+    while (j != validValues.second)
-+    {
-+        if (*j == setting.value) return true;
-+        ++j;
-+    }
-+    return false;
-+}
-+
-+bool GrFeatureParser::isCharId(const std::string & id, size_t offset, size_t length)
-+{
-+    if (length > 4) return false;
-+    for (size_t i = 0; i < length; i++)
-+    {
-+        if (i > 0 && id[offset+i] == '\0') continue;
-+        if ((id[offset+i]) < 0x20 || (id[offset+i]) < 0)
-+            return false;
-+        if (i==0 && id[offset+i] < 0x41)
-+            return false;
-+    }
-+    return true;
-+}
-+
-+int GrFeatureParser::getCharId(const std::string & id, size_t offset, size_t length)
-+{
-+    FeatId charId;
-+    charId.num = 0;
-+#ifdef WORDS_BIGENDIAN
-+    for (size_t i = 0; i < length; i++)
-+    {
-+        charId.label[i] = id[offset+i];
-+    }
-+#else
-+    for (size_t i = 0; i < length; i++)
-+    {
-+        charId.label[3-i] = id[offset+i];
-+    }
-+#endif
-+    return charId.num;
-+}
-+
-+int GrFeatureParser::getIntValue(const std::string & id, size_t offset, size_t length)
-+{
-+    int value = 0;
-+    int sign = 1;
-+    for (size_t i = 0; i < length; i++)
-+    {
-+        switch (id[offset + i])
-+        {
-+        case '0':
-+        case '1':
-+        case '2':
-+        case '3':
-+        case '4':
-+        case '5':
-+        case '6':
-+        case '7':
-+        case '8':
-+        case '9':
-+            value *= 10;
-+            if (sign < 0)
-+            {
-+                value = -(id[offset + i] - '0');
-+                sign = 1;
-+            }
-+            value += (id[offset + i] - '0');
-+            break;
-+        case '-':
-+            if (i == 0)
-+                sign = -1;
-+            else
-+            {
-+                mbErrors = true;
-+                break;
-+            }
-+        default:
-+            mbErrors = true;
-+            break;
-+        }
-+    }
-+    return value;
-+}
-+
-+
-+sal_Int32 GrFeatureParser::hashCode() const
-+{
-+    union IsoHash { sal_Int32 mInt; gr::isocode mCode; };
-+    IsoHash isoHash;
-+    isoHash.mCode = maLang;
-+    sal_Int32 hash = isoHash.mInt;
-+    for (size_t i = 0; i < mnNumSettings; i++)
-+    {
-+        hash = (hash << 16) ^ ((maSettings[i].id << 8) | maSettings[i].value);
-+    }
-+    return hash;
-+}
-Index: vcl/source/glyphs/makefile.mk
-===================================================================
---- vcl/source/glyphs/makefile.mk	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/source/glyphs/makefile.mk	(.../cws/graphite01)	(Revision 265804)
-@@ -54,8 +54,29 @@
- 		$(SLO)$/gcach_rbmp.obj		\
- 		$(SLO)$/gcach_layout.obj	\
- 		$(SLO)$/gcach_ftyp.obj
-+
-+.IF "$(ENABLE_GRAPHITE)" != ""
-+CFLAGS+=-DENABLE_GRAPHITE
-+SLOFILES+=	$(SLO)$/graphite_adaptors.obj	\
-+		$(SLO)$/graphite_features.obj	\
-+		$(SLO)$/graphite_cache.obj	\
-+		$(SLO)$/graphite_textsrc.obj	\
-+		$(SLO)$/graphite_serverfont.obj	\
-+		$(SLO)$/graphite_layout.obj
- .ENDIF
- 
-+.ELSE
-+.IF "$(ENABLE_GRAPHITE)" == "TRUE"
-+# make use of stlport headerfiles
-+EXT_USE_STLPORT=TRUE
-+SLOFILES=\
-+		$(SLO)$/graphite_textsrc.obj	\
-+		$(SLO)$/graphite_cache.obj	\
-+		$(SLO)$/graphite_features.obj	\
-+		$(SLO)$/graphite_layout.obj
-+.ENDIF
-+.ENDIF
-+
- # --- Targets ------------------------------------------------------
- 
- .INCLUDE :  target.mk
-Index: vcl/source/glyphs/graphite_textsrc.hxx
-===================================================================
---- vcl/source/glyphs/graphite_textsrc.hxx	(.../tags/DEV300_m35)	(Revision 0)
-+++ vcl/source/glyphs/graphite_textsrc.hxx	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,112 @@
-+#ifndef _SV_GRAPHITETEXTSRC_HXX
-+#define _SV_GRAPHITETEXTSRC_HXX
-+//
-+// C++ Interface: Graphite to SAL adaptor classes
-+//
-+// Description: Implements the Graphite interfaces IGrTextSource and
-+//              IGrGraphics which provide Graphite with access to the
-+//              app's text storage system and the platform's font and
-+//              graphics systems.
-+//
-+// Author: Tim Eves <tim_eves at sil.org>
-+//
-+// Copyright: Copyright (C) 2003-2004 SIL International.
-+//            All rights reserved. Distributable under the terms of either
-+//            the Common Public License or the GNU Lesser General Public
-+//            License.
-+//
-+
-+// We need this to enable namespace support in libgrengine headers.
-+#define GR_NAMESPACE
-+
-+// Standard Library
-+#include <stdexcept>
-+// Platform
-+
-+#ifndef _SVWIN_H
-+#include <tools/svwin.h>
-+#endif
-+
-+#ifndef _SV_SVSYS_HXX
-+#include <svsys.h>
-+#endif
-+
-+#ifndef _SV_SALGDI_HXX
-+#include <vcl/salgdi.hxx>
-+#endif
-+
-+#ifndef _SV_SALLAYOUT_HXX
-+#include <vcl/sallayout.hxx>
-+#endif
-+
-+// Module
-+#include "vcl/dllapi.h"
-+
-+// Libraries
-+#include <graphite/GrClient.h>
-+#include <graphite/Font.h>
-+#include <graphite/ITextSource.h>
-+
-+// Module type definitions and forward declarations.
-+//
-+namespace grutils
-+{
-+    class GrFeatureParser;
-+}
-+// Implements the Adaptor pattern to adapt the LayoutArgs and the ServerFont interfaces to the
-+// gr::IGrTextSource interface.
-+// @author tse
-+//
-+class TextSourceAdaptor : public gr::ITextSource
-+{
-+public:
-+        TextSourceAdaptor(ImplLayoutArgs &layout_args, const int nContextLen) throw();
-+        ~TextSourceAdaptor();
-+        virtual gr::UtfType     utfEncodingForm();
-+        virtual size_t          getLength();
-+        virtual size_t          fetch(gr::toffset ichMin, size_t cch, gr::utf32 * prgchBuffer);
-+        virtual size_t          fetch(gr::toffset ichMin, size_t cch, gr::utf16 * prgchwBuffer);
-+        virtual size_t          fetch(gr::toffset ichMin, size_t cch, gr::utf8  * prgchsBuffer);
-+        virtual bool            getRightToLeft(gr::toffset ich);
-+        virtual unsigned int    getDirectionDepth(gr::toffset ich);
-+        virtual float           getVerticalOffset(gr::toffset ich);
-+        virtual gr::isocode     getLanguage(gr::toffset ich);
-+
-+        virtual std::pair<gr::toffset, gr::toffset> propertyRange(gr::toffset ich);
-+        virtual size_t  getFontFeatures(gr::toffset ich, gr::FeatureSetting * prgfset);
-+        virtual bool    sameSegment(gr::toffset ich1, gr::toffset ich2);
-+
-+        operator ImplLayoutArgs & () throw();
-+        void setFeatures(const grutils::GrFeatureParser * pFeatures);
-+        const ImplLayoutArgs & getLayoutArgs() const { return maLayoutArgs; }
-+        size_t          getContextLength() const { return mnEnd; };
-+        inline void switchLayoutArgs(ImplLayoutArgs & newArgs);
-+private:
-+        // Prevent the generation of a default assignment operator.
-+        TextSourceAdaptor & operator=(const TextSourceAdaptor &);
-+
-+        void getCharProperties(const int, int &, int &, size_t &);
-+
-+        ImplLayoutArgs  maLayoutArgs;
-+        size_t    mnEnd;
-+        const grutils::GrFeatureParser * mpFeatures;
-+};
-+
-+inline TextSourceAdaptor::TextSourceAdaptor(ImplLayoutArgs &la, const int nContextLen) throw()
-+  : maLayoutArgs(la),
-+    mnEnd(std::min(la.mnLength, nContextLen)),
-+    mpFeatures(NULL)
-+{
-+}
-+
-+inline  TextSourceAdaptor::operator ImplLayoutArgs & () throw() {
-+        return maLayoutArgs;
-+}
-+
-+inline void TextSourceAdaptor::switchLayoutArgs(ImplLayoutArgs & aNewArgs)
-+{
-+    mnEnd += aNewArgs.mnMinCharPos - maLayoutArgs.mnMinCharPos;
-+    maLayoutArgs = aNewArgs;
-+}
-+
-+#endif
-Index: vcl/source/glyphs/graphite_cache.cxx
-===================================================================
---- vcl/source/glyphs/graphite_cache.cxx	(.../tags/DEV300_m35)	(Revision 0)
-+++ vcl/source/glyphs/graphite_cache.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,198 @@
-+/*************************************************************************
-+ *
-+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
-+ *
-+ * Copyright 2008 by Sun Microsystems, Inc.
-+ *
-+ * OpenOffice.org - a multi-platform office productivity suite
-+ *
-+ * $RCSfile: graphite_cache.cxx,v $
-+ * $Revision: 1.1.2.1 $
-+ *
-+ * This file is part of OpenOffice.org.
-+ *
-+ * OpenOffice.org is free software: you can redistribute it and/or modify
-+ * it under the terms of the GNU Lesser General Public License version 3
-+ * only, as published by the Free Software Foundation.
-+ *
-+ * OpenOffice.org is distributed in the hope that it will be useful,
-+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-+ * GNU Lesser General Public License version 3 for more details
-+ * (a copy is included in the LICENSE file that accompanied this code).
-+ *
-+ * You should have received a copy of the GNU Lesser General Public License
-+ * version 3 along with OpenOffice.org.  If not, see
-+ * <http://www.openoffice.org/license.html>
-+ * for a copy of the LGPLv3 License.
-+ *
-+ ************************************************************************/
-+
-+#ifdef MSC
-+#include <tools/svwin.h>
-+#include <svsys.h>
-+#endif
-+
-+#include <tools/debug.hxx>
-+#include <vcl/sallayout.hxx>
-+
-+#include <graphite/GrClient.h>
-+#include <graphite/Segment.h>
-+
-+#include <rtl/ustring.hxx>
-+#include <vcl/graphite_layout.hxx>
-+#include <vcl/graphite_cache.hxx>
-+
-+#include "graphite_textsrc.hxx"
-+
-+GrSegRecord::GrSegRecord(rtl::OUString * rope, TextSourceAdaptor * textSrc, gr::Segment * seg, bool bIsRtl)
-+    : m_rope(rope), m_text(textSrc), m_seg(seg), m_nextKey(NULL),
-+    m_fontScale(0.0f), mbIsRtl(bIsRtl), m_lockCount(0)
-+{
-+	m_pStr = textSrc->getLayoutArgs().mpStr + seg->startCharacter();
-+	m_startChar = seg->startCharacter();
-+}
-+
-+GrSegRecord::~GrSegRecord()
-+{
-+	clear();
-+}
-+
-+void GrSegRecord::reuse(rtl::OUString * rope, TextSourceAdaptor * textSrc, gr::Segment * seg, bool bIsRtl)
-+{
-+    clear();
-+    mnWidth = 0;
-+    m_rope = rope;
-+    m_text = textSrc;
-+    m_seg = seg;
-+    m_nextKey = NULL;
-+    m_pStr = textSrc->getLayoutArgs().mpStr + seg->startCharacter();
-+    m_startChar = seg->startCharacter();
-+    mbIsRtl = bIsRtl;
-+}
-+
-+void GrSegRecord::clearVectors()
-+{
-+    mvGlyphs.clear();
-+    mvCharDxs.clear();
-+    mvChar2BaseGlyph.clear();
-+    mvGlyph2Char.clear();
-+}
-+
-+void GrSegRecord::clear()
-+{
-+#ifdef GR_DEBUG_TEXT
-+    if (m_lockCount != 0)
-+      OutputDebugString("GrSegRecord locked!");
-+#endif
-+    clearVectors();
-+    delete m_rope;
-+    delete m_seg;
-+    delete m_text;
-+    m_rope = NULL;
-+    m_seg = NULL;
-+    m_text = NULL;
-+    m_fontScale = 0.0f;
-+    m_lockCount = 0;
-+}
-+
-+GrSegRecord * GraphiteSegmentCache::cacheSegment(TextSourceAdaptor * adapter, gr::Segment * seg, bool bIsRtl)
-+{
-+    GrSegRecord * record = NULL;
-+    // We keep a record of the oldest key and the last key added
-+    // when the next key is added, the record for the prevKey's m_nextKey field
-+    // is updated to the newest key so that m_oldestKey can be updated to the
-+    // next oldest key when the record for m_oldestKey is deleted
-+    if (m_segMap.size() > SEG_CACHE_SIZE)
-+    {
-+      GraphiteSegMap::iterator oldestPair = m_segMap.find(reinterpret_cast<long>(m_oldestKey));
-+      // oldest record may no longer exist if a buffer was changed
-+      if (oldestPair != m_segMap.end())
-+      {
-+        record = oldestPair->second;
-+        m_segMap.erase(reinterpret_cast<long>(m_oldestKey));
-+        GrRMEntry range = m_ropeMap.equal_range((*(record->m_rope)).hashCode());
-+        while (range.first != range.second)
-+        {
-+          if (range.first->second == record)
-+          {
-+            m_ropeMap.erase(range.first);
-+            break;
-+          }
-+          ++range.first;
-+        }
-+        m_oldestKey = record->m_nextKey;
-+        // record will be reused, so don't delete
-+      }
-+	}
-+
-+
-+//    const int seg_char_limit = min(adapter->maLayoutArgs().mnLength,
-+//      adapter->maLayoutArgs().mnEndCharPos
-+//      + GraphiteLayout::EXTRA_CONTEXT_LENGTH);
-+//    if (seg->stopCharacter() - seg->startCharacter() <= 0)
-+//      OutputDebugString("Invalid seg indices\n");
-+    rtl::OUString * pRope = new rtl::OUString(adapter->getLayoutArgs().mpStr + seg->startCharacter(),
-+       seg->stopCharacter() - seg->startCharacter());
-+    if (!pRope) return NULL;
-+    bool reuse = false;
-+    if (record)
-+      record->reuse(pRope, adapter, seg, bIsRtl);
-+    else
-+      record = new GrSegRecord(pRope, adapter, seg, bIsRtl);
-+    if (!record)
-+    {
-+      delete pRope;
-+      return NULL;
-+    }
-+    GraphiteSegMap::iterator iMap =
-+      m_segMap.find(reinterpret_cast<long>(record->m_pStr));
-+    if (iMap != m_segMap.end())
-+    {
-+      // the buffer has changed, so the old cached Segment is useless
-+      reuse = true;
-+      GrSegRecord * found = iMap->second;
-+      // Note: we reuse the old next key to avoid breaking our history
-+      // chain. This means it will be prematurely deleted, but this is
-+      // unlikely to happen very often.
-+      record->m_nextKey = found->m_nextKey;
-+      // overwrite the old record
-+      m_segMap[reinterpret_cast<long>(record->m_pStr)] = record;
-+      // erase the old rope key and save the new one
-+      GrRMEntry range = m_ropeMap.equal_range((*(found->m_rope)).hashCode());
-+      while (range.first != range.second)
-+      {
-+        if (range.first->second == found)
-+        {
-+          m_ropeMap.erase(range.first);
-+          break;
-+        }
-+        ++range.first;
-+      }
-+      GraphiteRopeMap::value_type mapEntry(record->m_rope->hashCode(), record);
-+      m_ropeMap.insert(mapEntry);
-+      // remove the old record
-+      delete found;
-+      record->m_lockCount++;
-+      return record;
-+    }
-+    m_segMap[reinterpret_cast<long>(record->m_pStr)] = record;
-+    GraphiteRopeMap::value_type mapEntry((*(record->m_rope)).hashCode(), record);
-+    m_ropeMap.insert(mapEntry);
-+
-+    if (m_oldestKey == NULL)
-+    {
-+      m_oldestKey = record->m_pStr;
-+      m_prevKey = record->m_pStr;
-+    }
-+    else if (reuse == false)
-+    {
-+      DBG_ASSERT(m_segMap.count(reinterpret_cast<long>(m_prevKey)),
-+        "Previous key got lost somehow!");
-+      m_segMap.find(reinterpret_cast<long>(m_prevKey))
-+        ->second->m_nextKey = record->m_pStr;
-+      m_prevKey = record->m_pStr;
-+    }
-+    record->m_lockCount++;
-+    return record;
-+}
-Index: vcl/source/glyphs/gcach_ftyp.cxx
-===================================================================
---- vcl/source/glyphs/gcach_ftyp.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/source/glyphs/gcach_ftyp.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -1399,6 +1399,20 @@
-         FT_Glyph_Transform( pGlyphFT, &aMatrix, NULL );
-     }
- 
-+    // Check for zero area bounding boxes as this crashes some versions of FT.
-+    // This also provides a handy short cut as much of the code following
-+    //  becomes an expensive nop when a glyph covers no pixels.
-+    FT_BBox cbox;
-+    FT_Glyph_Get_CBox(pGlyphFT, ft_glyph_bbox_unscaled, &cbox);
-+  
-+    if( (cbox.xMax - cbox.xMin) == 0 || (cbox.yMax - cbox.yMin == 0) )
-+    {
-+        nAngle = 0;
-+        memset(&rRawBitmap, 0, sizeof rRawBitmap);
-+        FT_Done_Glyph( pGlyphFT );
-+        return true;
-+    }
-+    
-     if( pGlyphFT->format != FT_GLYPH_FORMAT_BITMAP )
-     {
-         if( pGlyphFT->format == FT_GLYPH_FORMAT_OUTLINE )
-Index: vcl/source/glyphs/glyphcache.cxx
-===================================================================
---- vcl/source/glyphs/glyphcache.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/source/glyphs/glyphcache.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -41,6 +41,10 @@
- #include <vcl/bitmap.hxx>
- #include <vcl/outfont.hxx>
- 
-+#ifdef ENABLE_GRAPHITE
-+#include <vcl/graphite_features.hxx>
-+#endif
-+
- #include <rtl/ustring.hxx>		// used only for string=>hashvalue
- #include <osl/file.hxx>
- #include <tools/debug.hxx>
-@@ -85,12 +89,23 @@
- {
-     // TODO: is it worth to improve this hash function?
-     sal_IntPtr nFontId = reinterpret_cast<sal_IntPtr>( rFontSelData.mpFontData );
-+#ifdef ENABLE_GRAPHITE
-+    if (rFontSelData.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
-+        != STRING_NOTFOUND)
-+    {
-+        rtl::OString aFeatName = rtl::OUStringToOString( rFontSelData.maTargetName, RTL_TEXTENCODING_UTF8 );
-+        nFontId ^= aFeatName.hashCode();
-+    }
-+#endif
-     size_t nHash = nFontId << 8;
-     nHash   += rFontSelData.mnHeight;
-     nHash   += rFontSelData.mnOrientation;
-     nHash   += rFontSelData.mbVertical;
-     nHash   += rFontSelData.meItalic;
-     nHash   += rFontSelData.meWeight;
-+#ifdef ENABLE_GRAPHITE
-+    nHash   += rFontSelData.meLanguage;
-+#endif
-     return nHash;
- }
- 
-@@ -121,7 +136,16 @@
-     if( (rA.mnWidth != rB.mnWidth)
-     && ((rA.mnHeight != rB.mnWidth) || (rA.mnWidth != 0)) )
-         return false;
--
-+#ifdef ENABLE_GRAPHITE
-+   if (rA.meLanguage != rB.meLanguage)
-+        return false;
-+   // check for features
-+   if ((rA.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
-+        != STRING_NOTFOUND ||
-+        rB.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
-+        != STRING_NOTFOUND) && rA.maTargetName != rB.maTargetName)
-+        return false;
-+#endif
-     return true;
- }
- 
-Index: vcl/inc/vcl/graphite_serverfont.hxx
-===================================================================
---- vcl/inc/vcl/graphite_serverfont.hxx	(.../tags/DEV300_m35)	(Revision 0)
-+++ vcl/inc/vcl/graphite_serverfont.hxx	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,74 @@
-+#ifndef _SV_GRAPHITESERVERFONT_HXX
-+#define _SV_GRAPHITESERVERFONT_HXX
-+//
-+// C++ Interface: GraphiteLayout
-+//
-+// Description: An implementation of the SalLayout interface that uses the
-+//              Graphite engine.
-+//
-+// Author: Tim Eves <tim_eves at sil.org>
-+//
-+// Copyright: Copyright (C) 2003 SIL International.
-+//            All rights reserved. Distributable under the terms of either
-+//            the Common Public License or the GNU Lesser General Public
-+//            License.
-+//
-+
-+// We need this to enable namespace support in libgrengine headers.
-+#define GR_NAMESPACE
-+
-+#ifndef MSC
-+#include <vcl/graphite_layout.hxx>
-+#include <vcl/graphite_adaptors.hxx>
-+
-+// Modules
-+
-+// This class implments the server font specific parts.
-+// @author tse
-+//
-+class VCL_DLLPUBLIC GraphiteServerFontLayout : public ServerFontLayout
-+{
-+private:
-+        mutable GraphiteFontAdaptor * mpFont;
-+        // mutable so that the DrawOffset/DrawBase can be set
-+        mutable GraphiteLayout maImpl;
-+public:
-+        GraphiteServerFontLayout(GraphiteFontAdaptor * font) throw();
-+
-+        virtual bool  LayoutText( ImplLayoutArgs& rArgs) { SalLayout::AdjustLayout(rArgs); return maImpl.LayoutText(rArgs); };    // first step of layout
-+        virtual void  AdjustLayout( ImplLayoutArgs& rArgs)
-+        {
-+            SalLayout::AdjustLayout(rArgs);
-+            maImpl.DrawBase() = maDrawBase;
-+            maImpl.DrawOffset() = maDrawOffset;
-+            maImpl.AdjustLayout(rArgs);
-+        };
-+        virtual long    GetTextWidth() const                           { return maImpl.GetTextWidth(); }
-+        virtual long    FillDXArray( sal_Int32* dxa ) const                 { return maImpl.FillDXArray(dxa); }
-+        virtual int     GetTextBreak( long mw, long ce, int f ) const  { return maImpl.GetTextBreak(mw, ce, f); }
-+        virtual void    GetCaretPositions( int as, sal_Int32* cxa ) const   { maImpl.GetCaretPositions(as, cxa); }
-+
-+        // used by display layers
-+        virtual int     GetNextGlyphs( int l, sal_GlyphId* gia, Point& p, int& s,
-+                        sal_Int32* gaa = NULL, int* cpa = NULL ) const
-+        {
-+            maImpl.DrawBase() = maDrawBase;
-+            maImpl.DrawOffset() = maDrawOffset;
-+            return maImpl.GetNextGlyphs(l, gia, p, s, gaa, cpa);
-+        }
-+
-+        virtual void    MoveGlyph( int nStart, long nNewXPos ) { maImpl.MoveGlyph(nStart, nNewXPos); };
-+        virtual void    DropGlyph( int nStart ) { maImpl.DropGlyph(nStart); };
-+        virtual void    Simplify( bool bIsBase ) { maImpl.Simplify(bIsBase); };
-+
-+        virtual ~GraphiteServerFontLayout() throw();
-+
-+// For use with PspGraphics
-+        const sal_Unicode* getTextPtr() const;
-+        int getMinCharPos() const { return mnMinCharPos; }
-+        int getMaxCharPos() const { return mnEndCharPos; }
-+};
-+
-+
-+#endif
-+#endif //_SV_GRAPHITESERVERFONT_HXX
-Index: vcl/inc/vcl/graphite_layout.hxx
-===================================================================
---- vcl/inc/vcl/graphite_layout.hxx	(.../tags/DEV300_m35)	(Revision 0)
-+++ vcl/inc/vcl/graphite_layout.hxx	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,149 @@
-+#ifndef _SV_GRAPHITELAYOUT_HXX
-+#define _SV_GRAPHITELAYOUT_HXX
-+//
-+// C++ Interface: GraphiteLayout
-+//
-+// Description: An implementation of the SalLayout interface that uses the
-+//              Graphite engine.
-+//
-+// Author: Tim Eves <tim_eves at sil.org>
-+//         Keith Stribley <devel at thanlwinsoft.org>
-+//
-+// Copyright: Copyright (C) 2003 SIL International.
-+//            All rights reserved. Distributable under the terms of either
-+//            the Common Public License or the GNU Lesser General Public
-+//            License.
-+//
-+
-+// We need this to enable namespace support in libgrengine headers.
-+#define GR_NAMESPACE
-+
-+#define GRCACHE 1
-+
-+// Standard Library
-+#include <memory>
-+#include <vector>
-+#include <utility>
-+// Libraries
-+#include <graphite/GrClient.h>
-+#include <graphite/Font.h>
-+#include <graphite/GrConstants.h>
-+#include <graphite/GrAppData.h>
-+#include <graphite/SegmentAux.h>
-+// Platform
-+#include <vcl/sallayout.hxx>
-+#include <vcl/dllapi.h>
-+// Module
-+
-+// For backwards compatibility with 2.4.x
-+#if (SUPD == 680)
-+typedef sal_Int32 sal_GlyphId;
-+#endif
-+
-+
-+// Module type definitions and forward declarations.
-+//
-+class TextSourceAdaptor;
-+class GraphiteFontAdaptor;
-+class GrSegRecord;
-+// SAL/VCL types
-+class ServerFont;
-+// Graphite types
-+namespace gr { class Segment; class GlyphIterator; }
-+namespace grutils { class GrFeatureParser; }
-+
-+// This class uses the SIL Graphite engine to provide complex text layout services to the VCL
-+// @author tse
-+//
-+class VCL_DLLPUBLIC GraphiteLayout : public SalLayout
-+{
-+public:
-+    class Glyphs : public std::vector<GlyphItem>
-+    {
-+    public:
-+        typedef std::pair<Glyphs::const_iterator, Glyphs::const_iterator> iterator_pair_t;
-+
-+        static const int ADJUSTED;
-+
-+        void    fill_from(gr::Segment & rSeg, ImplLayoutArgs & rArgs,
-+            bool bRtl, long &rWidth, float fScaling,
-+            std::vector<int> & rChar2Base, std::vector<int> & rGlyph2Char,
-+            std::vector<int> & rCharDxs);
-+        void    move_glyph(Glyphs::iterator, long dx);
-+
-+        const_iterator    cluster_base(const_iterator) const;
-+        iterator_pair_t    neighbour_clusters(const_iterator) const;
-+    private:
-+        std::pair<float,float> appendCluster(gr::Segment & rSeg, ImplLayoutArgs & rArgs,
-+            bool bRtl, int nFirstCharInCluster, int nNextChar,
-+            int nFirstGlyphInCluster, int nNextGlyph, float fScaling,
-+            std::vector<int> & rChar2Base, std::vector<int> & rGlyph2Char,
-+            std::vector<int> & rCharDxs, long & rDXOffset);
-+        void         append(gr::Segment & rSeg, ImplLayoutArgs & rArgs, gr::GlyphInfo & rGi, float nextGlyphOrigin, float fScaling, std::vector<int> & rChar2Base, std::vector<int> & rGlyph2Char, std::vector<int> & rCharDxs, long & rDXOffset, bool bIsBase);
-+    };
-+
-+    mutable Glyphs          mvGlyphs;
-+    void clear();
-+
-+private:
-+    TextSourceAdaptor     * mpTextSrc; // Text source.
-+    gr::LayoutEnvironment   maLayout;
-+    const gr::Font         &mrFont;
-+    long                    mnWidth;
-+    std::vector<int>        mvCharDxs;
-+    std::vector<int>        mvChar2BaseGlyph;
-+    std::vector<int>        mvGlyph2Char;
-+    float                   mfScaling;
-+    const grutils::GrFeatureParser * mpFeatures;
-+
-+public:
-+    GraphiteLayout(const gr::Font & font, const grutils::GrFeatureParser * features = NULL) throw();
-+
-+    // used by upper layers
-+    virtual bool  LayoutText( ImplLayoutArgs& );    // first step of layout
-+    // split into two stages to allow dc to be restored on the segment
-+#ifdef GRCACHE
-+    gr::Segment * CreateSegment(ImplLayoutArgs& rArgs, GrSegRecord ** pRecord = NULL);
-+    bool LayoutGlyphs(ImplLayoutArgs& rArgs, gr::Segment * pSegment, GrSegRecord * pSegRecord);
-+#else
-+    gr::Segment * CreateSegment(ImplLayoutArgs& rArgs);
-+    bool LayoutGlyphs(ImplLayoutArgs& rArgs, gr::Segment * pSegment);
-+#endif
-+
-+    virtual void  AdjustLayout( ImplLayoutArgs& );  // adjusting positions
-+
-+    // methods using string indexing
-+    virtual int   GetTextBreak( long nMaxWidth, long nCharExtra=0, int nFactor=1 ) const;
-+    virtual long  FillDXArray( sal_Int32* pDXArray ) const;
-+    virtual void  ApplyDXArray(ImplLayoutArgs &args);
-+
-+    virtual void  GetCaretPositions( int nArraySize, sal_Int32* pCaretXArray ) const;
-+
-+    // methods using glyph indexing
-+    virtual int   GetNextGlyphs(int nLen, sal_GlyphId* pGlyphIdxAry, ::Point & rPos, int&,
-+            sal_Int32* pGlyphAdvAry = 0, int* pCharPosAry = 0 ) const;
-+
-+    // used by glyph+font+script fallback
-+    virtual void    MoveGlyph( int nStart, long nNewXPos );
-+    virtual void    DropGlyph( int nStart );
-+    virtual void    Simplify( bool bIsBase );
-+
-+    // Dummy implementation so layout can be shared between Linux/Windows
-+    virtual void    DrawText(SalGraphics&) const {};
-+
-+    virtual ~GraphiteLayout() throw();
-+    void SetFeatures(grutils::GrFeatureParser * aFeature) { mpFeatures = aFeature; }
-+    void SetFontScale(float s) { mfScaling = s; };
-+    const TextSourceAdaptor * textSrc() const { return mpTextSrc; };
-+
-+    static const int EXTRA_CONTEXT_LENGTH;
-+private:
-+    int                   glyph_to_char(Glyphs::iterator);
-+    std::pair<int,int>    glyph_to_chars(const GlyphItem &) const;
-+
-+    std::pair<long,long>  caret_positions(size_t) const;
-+};
-+
-+
-+
-+#endif // _SV_GRAPHITELAYOUT_HXX
-Index: vcl/inc/vcl/graphite_adaptors.hxx
-===================================================================
---- vcl/inc/vcl/graphite_adaptors.hxx	(.../tags/DEV300_m35)	(Revision 0)
-+++ vcl/inc/vcl/graphite_adaptors.hxx	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,139 @@
-+#ifndef _SV_GRAPHITEADAPTORS_HXX
-+#define _SV_GRAPHITEADAPTORS_HXX
-+//
-+// C++ Interface: Graphite to SAL adaptor classes
-+//
-+// Description: Implements the Graphite interfaces IGrTextSource and
-+//              IGrGraphics which provide Graphite with access to the
-+//              app's text storage system and the platform's font and
-+//              graphics systems.
-+//
-+// Author: Tim Eves <tim_eves at sil.org>
-+//
-+// Copyright: Copyright (C) 2003-2004 SIL International.
-+//            All rights reserved. Distributable under the terms of either
-+//            the Common Public License or the GNU Lesser General Public
-+//            License.
-+//
-+
-+// We need this to enable namespace support in libgrengine headers.
-+#define GR_NAMESPACE
-+
-+// Standard Library
-+#include <stdexcept>
-+// Platform
-+
-+#ifndef _SVWIN_H
-+#include <tools/svwin.h>
-+#endif
-+
-+#ifndef _SV_SVSYS_HXX
-+#include <svsys.h>
-+#endif
-+
-+#ifndef _SV_SALGDI_HXX
-+#include <vcl/salgdi.hxx>
-+#endif
-+
-+#ifndef _SV_SALLAYOUT_HXX
-+#include <vcl/sallayout.hxx>
-+#endif
-+
-+// Module
-+#include "vcl/dllapi.h"
-+
-+// Libraries
-+#include <graphite/GrClient.h>
-+#include <graphite/Font.h>
-+#include <graphite/ITextSource.h>
-+
-+
-+// Module type definitions and forward declarations.
-+//
-+#ifndef MSC
-+// SAL/VCL types
-+class ServerFont;
-+class FreetypeServerFont;
-+
-+// Graphite types
-+
-+struct FontProperties : gr::FontProps
-+{
-+    FontProperties(const FreetypeServerFont & font) throw();
-+};
-+
-+namespace grutils
-+{
-+    class GrFeatureParser;
-+}
-+
-+// This class adapts the Sal font and graphics services to form required by
-+// the Graphite engine.
-+// @author tse
-+//
-+class VCL_DLLPUBLIC GraphiteFontAdaptor : public gr::Font
-+{
-+typedef std::map<gr::gid16, std::pair<gr::Rect, gr::Point> > GlyphMetricMap;
-+
-+public:
-+    static bool    IsGraphiteEnabledFont(ServerFont &) throw();
-+
-+    GraphiteFontAdaptor(ServerFont & font, const sal_Int32 dpi_x, const sal_Int32 dpi_y);
-+    GraphiteFontAdaptor(const GraphiteFontAdaptor &) throw();
-+    ~GraphiteFontAdaptor() throw();
-+
-+     gr::Font    * copyThis();
-+
-+    // Basic attribute accessors.
-+    virtual float        ascent();
-+    virtual float        descent();
-+    virtual bool        bold();
-+    virtual bool        italic();
-+    virtual float        height();
-+    virtual unsigned int    getDPIx();
-+    virtual unsigned int    getDPIy();
-+
-+    // Font access methods.
-+    virtual const void    * getTable(gr::fontTableId32 tableID, size_t * pcbSize);
-+    virtual void          getFontMetrics(float * ascent_out, float * descent_out = 0, float * em_square_out = 0);
-+
-+    // Glyph metrics.
-+    virtual void      getGlyphMetrics(gr::gid16 glyphID, gr::Rect & boundingBox, gr::Point & advances);
-+
-+    // Adaptor attributes.
-+    const FontProperties    & fontProperties() const throw();
-+    FreetypeServerFont        & font() const throw();
-+    const grutils::GrFeatureParser * features() const { return mpFeatures; };
-+
-+private:
-+    virtual void UniqueCacheInfo(std::wstring &, bool &, bool &);
-+
-+    FreetypeServerFont& mrFont;
-+    FontProperties        maFontProperties;
-+    const unsigned int    mnDpiX, mnDpiY;
-+    const float           mfAscent,
-+                    mfDescent,
-+                    mfEmUnits;
-+    grutils::GrFeatureParser * mpFeatures;
-+    GlyphMetricMap maGlyphMetricMap;
-+};
-+
-+// Partial implementation of class GraphiteFontAdaptor.
-+//
-+inline const FontProperties & GraphiteFontAdaptor::fontProperties() const throw() {
-+    return maFontProperties;
-+}
-+
-+inline FreetypeServerFont & GraphiteFontAdaptor::font() const throw() {
-+    return mrFont;
-+}
-+#endif // not MFC
-+
-+// Partial implementation of class TextSourceAdaptor.
-+//
-+//inline const ImplLayoutArgs & TextSourceAdaptor::layoutArgs() const throw() {
-+//  return _layout_args;
-+//}
-+
-+
-+#endif // _SV_GRAPHITEADAPTORS_HXX
-Index: vcl/inc/vcl/graphite_cache.hxx
-===================================================================
---- vcl/inc/vcl/graphite_cache.hxx	(.../tags/DEV300_m35)	(Revision 0)
-+++ vcl/inc/vcl/graphite_cache.hxx	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,245 @@
-+//
-+// C++ Implementation: GraphiteLayout
-+//
-+// Description: A Class to cache Graphite Segments to try to improve
-+//              rendering performance.
-+//
-+// Author: Keith Stribley <devel at thanlwinsoft.org>
-+// Contributors:
-+//
-+// Copyright: Copyright (C) 2006, 2008 SIL International.
-+//            All rights reserved. Distributable under the terms of either
-+//            the Common Public License or the GNU Lesser General Public
-+//            License.
-+//
-+#ifndef GraphiteSegmentCache_h
-+#define GraphiteSegmentCache_h
-+
-+#include <tools/solar.h>
-+#include <rtl/ustring.h>
-+
-+#define GRCACHE_REUSE_VECTORS 1
-+
-+//#include <rope>
-+#include <hash_map>
-+
-+class TextSourceAdaptor;
-+/**
-+* GrSegRecord stores a Graphite Segment and its associated text
-+*/
-+class GrSegRecord {
-+public:
-+    GrSegRecord(rtl::OUString * rope, TextSourceAdaptor * textSrc, gr::Segment * seg, bool bIsRtl);
-+
-+    ~GrSegRecord();
-+
-+    void reuse(rtl::OUString * rope, TextSourceAdaptor * textSrc, gr::Segment * seg, bool bIsRtl);
-+
-+    void clearVectors();
-+    void clear();
-+#ifdef GRCACHE_REUSE_VECTORS
-+    void setGlyphVectors(long nWidth, GraphiteLayout::Glyphs & vGlyphs, std::vector<int> vCharDxs,
-+                         std::vector<int> & vChar2Base, std::vector<int> & vGlyph2Char)
-+    {
-+        clearVectors();
-+        mnWidth = nWidth;
-+        mvGlyphs.insert(mvGlyphs.begin(), vGlyphs.begin(), vGlyphs.end());
-+        mvCharDxs.insert(mvCharDxs.begin(),vCharDxs.begin(),vCharDxs.end());
-+        mvChar2BaseGlyph.insert(mvChar2BaseGlyph.begin(),vChar2Base.begin(),vChar2Base.end());
-+        mvGlyph2Char.insert(mvGlyph2Char.begin(),vGlyph2Char.begin(),vGlyph2Char.end());
-+    }
-+#endif
-+    gr::Segment * getSegment() { return m_seg; }
-+    TextSourceAdaptor * getTextSrc() { return m_text; }
-+    void unlock() { --m_lockCount; }
-+    bool isRtl() const { return mbIsRtl; }
-+#ifdef GRCACHE_REUSE_VECTORS
-+    const long width() const { return mnWidth; }
-+    const GraphiteLayout::Glyphs & glyphs() const { return mvGlyphs; }
-+    const std::vector<int> & charDxs() const { return mvCharDxs; }
-+    const std::vector<int> & char2BaseGlyph() const { return mvChar2BaseGlyph; }
-+    const std::vector<int> & glyph2Char() const { return mvGlyph2Char; }
-+#endif
-+private:
-+    rtl::OUString * m_rope;
-+    TextSourceAdaptor * m_text;
-+    gr::Segment * m_seg;
-+    const xub_Unicode * m_nextKey;
-+    const xub_Unicode*  m_pStr;
-+    size_t m_startChar;
-+    float m_fontScale;
-+    long mnWidth;
-+    GraphiteLayout::Glyphs mvGlyphs; // glyphs in display order
-+    std::vector<int> mvCharDxs; // right hand side x offset of each glyph
-+    std::vector<int> mvChar2BaseGlyph;
-+    std::vector<int> mvGlyph2Char;
-+    bool mbIsRtl;
-+    int m_lockCount;
-+    friend class GraphiteSegmentCache;
-+};
-+
-+typedef std::hash_map<long, GrSegRecord*, std::hash<long> > GraphiteSegMap;
-+typedef std::hash_multimap<size_t, GrSegRecord*> GraphiteRopeMap;
-+typedef std::pair<GraphiteRopeMap::iterator, GraphiteRopeMap::iterator> GrRMEntry;
-+
-+/**
-+* GraphiteSegmentCache contains the cached Segments for one particular font size
-+*/
-+class GraphiteSegmentCache
-+{
-+  enum {
-+    // not really sure what good values are here,
-+    // bucket size should be >> cache size
-+    SEG_BUCKET_SIZE = 4096,
-+    SEG_CACHE_SIZE = 255
-+  };
-+public:
-+  GraphiteSegmentCache()
-+    : m_segMap(SEG_BUCKET_SIZE),
-+    m_oldestKey(NULL) {};
-+  ~GraphiteSegmentCache()
-+  {
-+    m_ropeMap.clear();
-+    GraphiteSegMap::iterator i = m_segMap.begin();
-+    while (i != m_segMap.end())
-+    {
-+      GrSegRecord *r = i->second;
-+      delete r;
-+      ++i;
-+    }
-+    m_segMap.clear();
-+  };
-+  GrSegRecord * getSegment(ImplLayoutArgs & layoutArgs, bool bIsRtl)
-+  {
-+    GrSegRecord * found = NULL;
-+    // try to find a segment starting at correct place, if not, try to find a
-+    //  match for the complete buffer
-+    GraphiteSegMap::iterator iMap =
-+      m_segMap.find(reinterpret_cast<long>(layoutArgs.mpStr +
-+                                           layoutArgs.mnMinCharPos));
-+    if (iMap != m_segMap.end())
-+    {
-+      found = iMap->second;
-+    }
-+    else
-+    {
-+      iMap = m_segMap.find(reinterpret_cast<long>(layoutArgs.mpStr));
-+      if (iMap != m_segMap.end())
-+      {
-+        found = iMap->second;
-+      }
-+    }
-+    if (found)
-+    {
-+      if (found->m_seg->startCharacter() <= layoutArgs.mnMinCharPos &&
-+          found->m_seg->stopCharacter() >= layoutArgs.mnEndCharPos)
-+      {
-+        const size_t seg_char_limit = min(layoutArgs.mnLength, layoutArgs.mnEndCharPos
-+          + GraphiteLayout::EXTRA_CONTEXT_LENGTH);
-+        DBG_ASSERT(found && found->m_seg, "null entry in GraphiteSegmentCache");
-+        // restore original start character, in case it has changed
-+        found->m_seg->setTextSourceOffset(found->m_startChar);
-+        // check that characters are the same, at least in the range of
-+        // interest
-+        // We could use substr and ==, but substr does a copy,
-+        // so its probably faster to do it like this
-+        for (size_t i = layoutArgs.mnMinCharPos; i < seg_char_limit; i++)
-+        {
-+          //if (!found->m_rope->match(rtl::OUString(layoutArgs.mpStr[i], layoutArgs.mnLength), i - found->m_seg->startCharacter()))
-+          if (found->m_rope->getStr()[i-found->m_seg->startCharacter()] != layoutArgs.mpStr[i])
-+            return NULL;
-+        }
-+        if (found->isRtl() != bIsRtl)
-+        {
-+            return NULL;
-+        }
-+//        if (found->m_lockCount != 0)
-+//          OutputDebugString("Multple users of SegRecord!");
-+        found->m_lockCount++;
-+      }
-+      else found = NULL;
-+    }
-+    else
-+    {
-+      // the pointers aren't the same, but we might still have the same text in a segment
-+      // this is expecially needed when editing a large paragraph
-+      // each edit changes the pointers, but if we don't reuse any segments it gets very
-+      // slow.
-+      const size_t seg_char_limit = min(layoutArgs.mnLength, layoutArgs.mnEndCharPos
-+          + GraphiteLayout::EXTRA_CONTEXT_LENGTH);
-+      rtl::OUString * rope = new rtl::OUString(layoutArgs.mpStr + layoutArgs.mnMinCharPos,
-+                                         seg_char_limit - layoutArgs.mnMinCharPos);
-+      if (!rope) return NULL;
-+      GrRMEntry range = m_ropeMap.equal_range((*(rope)).hashCode());
-+      while (range.first != range.second)
-+      {
-+        found = range.first->second;
-+        if (found->m_lockCount == 0)
-+        {
-+          if(rope->match(*(found->m_rope)))
-+          {
-+            // found, but the pointers are all wrong
-+            found->m_seg->setTextSourceOffset(layoutArgs.mnMinCharPos);
-+            // the switch is done in graphite_layout.cxx
-+            //found->m_text->switchLayoutArgs(layoutArgs);
-+            found->m_lockCount++;
-+            break;
-+          }
-+          else
-+            found = NULL;
-+        }
-+        else
-+          found = NULL;
-+        ++(range.first);
-+      }
-+      delete rope;
-+    }
-+    return found;
-+  };
-+  GrSegRecord * cacheSegment(TextSourceAdaptor * adapter, gr::Segment * seg, bool bIsRtl);
-+private:
-+  GraphiteSegMap m_segMap;
-+  GraphiteRopeMap m_ropeMap;
-+  const xub_Unicode * m_oldestKey;
-+  const xub_Unicode * m_prevKey;
-+};
-+
-+typedef std::hash_map<int, GraphiteSegmentCache *, std::hash<int> > GraphiteCacheMap;
-+
-+/**
-+* GraphiteCacheHandler maps a particular font, style, size to a GraphiteSegmentCache
-+*/
-+class GraphiteCacheHandler
-+{
-+public:
-+  GraphiteCacheHandler() : m_cacheMap(255) {};
-+  ~GraphiteCacheHandler()
-+  {
-+    GraphiteCacheMap::iterator i = m_cacheMap.begin();
-+    while (i != m_cacheMap.end())
-+    {
-+      GraphiteSegmentCache *r = i->second;
-+      delete r;
-+      ++i;
-+    }
-+    m_cacheMap.clear();
-+  };
-+
-+  static GraphiteCacheHandler instance;
-+
-+  GraphiteSegmentCache * getCache(sal_Int32 & fontHash)
-+  {
-+    if (m_cacheMap.count(fontHash) > 0)
-+    {
-+      return m_cacheMap.find(fontHash)->second;
-+    }
-+    GraphiteSegmentCache *pCache = new GraphiteSegmentCache();
-+    m_cacheMap[fontHash] = pCache;
-+    return pCache;
-+  }
-+private:
-+  GraphiteCacheMap m_cacheMap;
-+};
-+
-+#endif
-+
-Index: vcl/inc/vcl/graphite_features.hxx
-===================================================================
---- vcl/inc/vcl/graphite_features.hxx	(.../tags/DEV300_m35)	(Revision 0)
-+++ vcl/inc/vcl/graphite_features.hxx	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,58 @@
-+/*-----------------------------------------------------------------------------
-+Copyright (C) 2008 www.thanlwinsoft.org
-+
-+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:
-+Responsibility: Keith Stribley
-+Last reviewed: Not yet.
-+
-+Description:
-+Parse a string of features specified as ; separated pairs.
-+e.g.
-+1001=1;2002=2;fav1=0
-+
-+-----------------------------------------------------------------------------*/
-+#include <graphite/GrClient.h>
-+#include <graphite/Font.h>
-+#include <graphite/GrFeature.h>
-+
-+namespace grutils
-+{
-+
-+    class GrFeatureParser
-+    {
-+    public:
-+        enum { MAX_FEATURES = 64 };
-+        static const char FEAT_PREFIX;
-+        static const char FEAT_SEPARATOR;
-+        static const char FEAT_ID_VALUE_SEPARATOR;
-+        static const std::string ISO_LANG;
-+        GrFeatureParser(gr::Font & font, const std::string features, const std::string lang);
-+        GrFeatureParser(gr::Font & font, const std::string lang);
-+        GrFeatureParser(const GrFeatureParser & copy);
-+        ~GrFeatureParser();
-+        size_t getFontFeatures(gr::FeatureSetting settings[MAX_FEATURES]) const;
-+        bool parseErrors() { return mbErrors; };
-+        static bool isValid(gr::Font & font, gr::FeatureSetting & setting);
-+        gr::isocode getLanguage() const { return maLang; };
-+        bool hasLanguage() const { return (maLang.rgch[0] != '\0'); }
-+        sal_Int32 hashCode() const;
-+    private:
-+        void setLang(gr::Font & font, const std::string & lang);
-+        bool isCharId(const std::string & id, size_t offset, size_t length);
-+        int getCharId(const std::string & id, size_t offset, size_t length);
-+        int getIntValue(const std::string & id, size_t offset, size_t length);
-+        size_t mnNumSettings;
-+        gr::isocode maLang;
-+        bool mbErrors;
-+        gr::FeatureSetting maSettings[64];
-+    };
-+
-+    union FeatId
-+    {
-+        gr::featid num;
-+        unsigned char label[5];
-+    };
-+}
-Index: vcl/unx/source/gdi/makefile.mk
-===================================================================
---- vcl/unx/source/gdi/makefile.mk	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/unx/source/gdi/makefile.mk	(.../cws/graphite01)	(Revision 265804)
-@@ -96,6 +96,10 @@
- CFLAGS+=-DXRENDER_LINK
- .ENDIF
- 
-+.IF "$(ENABLE_GRAPHITE)" == "TRUE"
-+CFLAGS+=-DENABLE_GRAPHITE
-+.ENDIF
-+
- .ENDIF	# "$(GUIBASE)"!="unx"
- 
- # --- Targets ------------------------------------------------------
-Index: vcl/unx/source/gdi/pspgraphics.cxx
-===================================================================
---- vcl/unx/source/gdi/pspgraphics.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/unx/source/gdi/pspgraphics.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -51,6 +51,11 @@
- #include <sys/stat.h>
- #include <sys/types.h>
- 
-+#ifdef ENABLE_GRAPHITE
-+#include <vcl/graphite_layout.hxx>
-+#include <vcl/graphite_serverfont.hxx>
-+#endif
-+
- using namespace psp;
- using namespace rtl;
- 
-@@ -702,9 +707,30 @@
- 
-     Point aPos;
-     long nUnitsPerPixel = rLayout.GetUnitsPerPixel();
--    const sal_Unicode* pText = bIsPspServerFontLayout ? static_cast<const PspServerFontLayout&>(rLayout).getTextPtr() : NULL;
--    int nMinCharPos = bIsPspServerFontLayout ? static_cast<const PspServerFontLayout&>(rLayout).getMinCharPos() : 0;
--    int nMaxCharPos = bIsPspServerFontLayout ? static_cast<const PspServerFontLayout&>(rLayout).getMaxCharPos() : 0;
-+    const sal_Unicode* pText = NULL;
-+    int nMinCharPos = 0;
-+    int nMaxCharPos = 0;
-+    if (bIsPspServerFontLayout)
-+    {
-+        const PspServerFontLayout * pPspLayout = dynamic_cast<const PspServerFontLayout*>(&rLayout);
-+#ifdef ENABLE_GRAPHITE
-+        const GraphiteServerFontLayout * pGrLayout = dynamic_cast<const GraphiteServerFontLayout*>(&rLayout);
-+#endif
-+        if (pPspLayout)
-+        {
-+            pText = pPspLayout->getTextPtr();
-+            nMinCharPos = pPspLayout->getMinCharPos();
-+            nMaxCharPos = pPspLayout->getMaxCharPos();
-+        }
-+#ifdef ENABLE_GRAPHITE
-+        else if (pGrLayout)
-+        {
-+            pText = pGrLayout->getTextPtr();
-+            nMinCharPos = pGrLayout->getMinCharPos();
-+            nMaxCharPos = pGrLayout->getMaxCharPos();
-+        }
-+#endif
-+    }
-     for( int nStart = 0;; )
-     {
-         int nGlyphCount = rLayout.GetNextGlyphs( nMaxGlyphs, aGlyphAry, aPos, nStart, aWidthAry, bIsPspServerFontLayout ? aCharPosAry : NULL );
-@@ -958,7 +984,21 @@
- 
-     if( m_pServerFont[ nFallbackLevel ]
-         && !(rArgs.mnFlags & SAL_LAYOUT_DISABLE_GLYPH_PROCESSING) )
--        pLayout = new PspServerFontLayout( *m_pPrinterGfx, *m_pServerFont[nFallbackLevel], rArgs );
-+    {
-+#ifdef ENABLE_GRAPHITE
-+        // Is this a Graphite font?
-+        if (GraphiteFontAdaptor::IsGraphiteEnabledFont(*m_pServerFont[nFallbackLevel]))
-+        {
-+            sal_Int32 xdpi, ydpi;
-+            GetResolution(xdpi, ydpi);
-+            GraphiteFontAdaptor * pGrfont = new GraphiteFontAdaptor( *m_pServerFont[nFallbackLevel], xdpi, ydpi);
-+            if (!pGrfont) return NULL;
-+            pLayout = new GraphiteServerFontLayout(pGrfont);
-+        }
-+        else
-+#endif
-+            pLayout = new PspServerFontLayout( *m_pPrinterGfx, *m_pServerFont[nFallbackLevel], rArgs );
-+    }
-     else
-         pLayout = new PspFontLayout( *m_pPrinterGfx );
- 
-Index: vcl/unx/source/gdi/salgdi3.cxx
-===================================================================
---- vcl/unx/source/gdi/salgdi3.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/unx/source/gdi/salgdi3.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -79,6 +79,11 @@
- 
- #include <hash_set>
- 
-+#ifdef ENABLE_GRAPHITE
-+#include <vcl/graphite_layout.hxx>
-+#include <vcl/graphite_serverfont.hxx>
-+#endif
-+
- struct cairo_surface_t;
- struct cairo_t;
- struct cairo_font_face_t;
-@@ -1688,11 +1693,28 @@
- 
- SalLayout* X11SalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel )
- {
--    GenericSalLayout* pLayout = NULL;
-+    SalLayout* pLayout = NULL;
- 
-     if( mpServerFont[ nFallbackLevel ]
-     && !(rArgs.mnFlags & SAL_LAYOUT_DISABLE_GLYPH_PROCESSING) )
--        pLayout = new ServerFontLayout( *mpServerFont[ nFallbackLevel ] );
-+    {
-+#ifdef ENABLE_GRAPHITE
-+        // Is this a Graphite font?
-+        if (GraphiteFontAdaptor::IsGraphiteEnabledFont(*mpServerFont[nFallbackLevel]))
-+        {
-+            sal_Int32 xdpi, ydpi;
-+
-+            xdpi = GetDisplay()->GetResolution().A();
-+            ydpi = GetDisplay()->GetResolution().B();
-+
-+            GraphiteFontAdaptor * pGrfont = new GraphiteFontAdaptor( *mpServerFont[nFallbackLevel], xdpi, ydpi);
-+            if (!pGrfont) return NULL;
-+            pLayout = new GraphiteServerFontLayout(pGrfont);
-+        }
-+        else
-+#endif
-+            pLayout = new ServerFontLayout( *mpServerFont[ nFallbackLevel ] );
-+    }
-     else if( mXFont[ nFallbackLevel ] )
-         pLayout = new X11FontLayout( *mXFont[ nFallbackLevel ] );
-     else
-Index: vcl/prj/build.lst
-===================================================================
---- vcl/prj/build.lst	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/prj/build.lst	(.../cws/graphite01)	(Revision 265804)
-@@ -1,4 +1,4 @@
--vc	vcl	:	apple_remote BOOST:boost psprint rsc sot ucbhelper unotools ICU:icu i18npool i18nutil unoil ridljar X11_EXTENSIONS:x11_extensions offuh basegfx basebmp tools transex3 icc NULL
-+vc	vcl	:	apple_remote BOOST:boost psprint rsc sot ucbhelper unotools ICU:icu GRAPHITE:graphite i18npool i18nutil unoil ridljar X11_EXTENSIONS:x11_extensions offuh basegfx basebmp tools transex3 icc NULL
- vc	vcl										usr1	-	all	vc_mkout NULL
- vc	vcl\inc									nmake	-	all	vc_inc NULL
- vc	vcl\source\glyphs						nmake	-	all	vc_glyphs vc_inc NULL
-Index: vcl/util/makefile.mk
-===================================================================
---- vcl/util/makefile.mk	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/util/makefile.mk	(.../cws/graphite01)	(Revision 265804)
-@@ -181,6 +181,16 @@
-             $(ICUUCLIB)			\
-             $(ICULELIB)			\
- 			$(JVMACCESSLIB)
-+
-+.IF "$(GUI)" == "UNX"
-+.IF "$(ENABLE_GRAPHITE)" == "TRUE"
-+.IF "$(SYSTEM_GRAPHITE)" == "YES"
-+SHL1STDLIBS+= $(GRAPHITE_LIBS)
-+.ELSE
-+SHL1STDLIBS+= $(SOLARVERSION)$/$(INPATH)$/lib$/libgraphite.a
-+.ENDIF
-+.ENDIF
-+.ENDIF
- SHL1USE_EXPORTS=name
- 
- .IF "$(GUIBASE)"=="aqua"
-@@ -197,6 +207,10 @@
- .IF "$(USE_BUILTIN_RASTERIZER)"!=""
-     LIB1FILES +=    $(SLB)$/glyphs.lib
-     SHL1STDLIBS+=   $(FREETYPELIB)  $(PSPLIB)
-+.ELSE
-+.IF "$(ENABLE_GRAPHITE)" == "TRUE"
-+    LIB1FILES +=    $(SLB)$/glyphs.lib
-+.ENDIF
- .ENDIF # USE_BUILTIN_RASTERIZER
- 
- SHL1LIBS=   $(LIB1TARGET)
-@@ -226,6 +240,14 @@
- SHL1STDLIBS += $(PSPLIB)
- .ENDIF
- 
-+.IF "$(ENABLE_GRAPHITE)" == "TRUE"
-+.IF "$(COM)" == "GCC"
-+SHL1STDLIBS += -lgraphite
-+.ELSE
-+SHL1STDLIBS += graphite_dll.lib
-+.ENDIF
-+.ENDIF
-+
- SHL1STDLIBS += $(UWINAPILIB)      \
-                $(GDI32LIB)        \
-                $(MSIMG32LIB)        \
-Index: vcl/win/source/gdi/MAKEFILE.MK
-===================================================================
---- vcl/win/source/gdi/MAKEFILE.MK	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/win/source/gdi/MAKEFILE.MK	(.../cws/graphite01)	(Revision 265804)
-@@ -64,6 +64,10 @@
- 
- EXCEPTIONSFILES=	$(SLO)$/salprn.obj
- 
-+.IF "$(ENABLE_GRAPHITE)" == "TRUE"
-+CFLAGS+=-DENABLE_GRAPHITE
-+.ENDIF
-+
- # --- Targets ------------------------------------------------------
- 
- .INCLUDE :  target.mk
-Index: vcl/win/source/gdi/salgdi3.cxx
-===================================================================
---- vcl/win/source/gdi/salgdi3.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/win/source/gdi/salgdi3.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -72,6 +72,10 @@
- #include <tools/stream.hxx>
- #include <rtl/bootstrap.hxx>
- 
-+#ifdef ENABLE_GRAPHITE
-+#include <graphite/GrClient.h>
-+#include <graphite/WinFont.h>
-+#endif
- 
- #include <vector>
- #include <set>
-@@ -806,6 +810,9 @@
-     mbDisableGlyphApi( false ),
-     mbHasKoreanRange( false ),
-     mbHasCJKSupport( false ),
-+#ifdef ENABLE_GRAPHITE
-+    mbHasGraphiteSupport( false ),
-+#endif
-     mbAliasSymbolsLow( false ),
-     mbAliasSymbolsHigh( false ),
-     mnId( 0 ),
-@@ -863,6 +870,9 @@
- 
-     ReadCmapTable( hDC );
-     ReadOs2Table( hDC );
-+#ifdef ENABLE_GRAPHITE
-+    mbHasGraphiteSupport = gr::WinFont::FontHasGraphiteTables(hDC);
-+#endif
- 
-     // even if the font works some fonts have problems with the glyph API
-     // => the heuristic below tries to figure out which fonts have the problem
-Index: vcl/win/source/gdi/winlayout.cxx
-===================================================================
---- vcl/win/source/gdi/winlayout.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/win/source/gdi/winlayout.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -65,6 +65,17 @@
- #include <set>
- typedef std::set<int> IntSet;
- 
-+// Graphite headers
-+#ifdef ENABLE_GRAPHITE
-+#include <i18npool/mslangid.hxx>
-+#include <graphite/GrClient.h>
-+#include <graphite/WinFont.h>
-+#include <graphite/Segment.h>
-+#include <vcl/graphite_layout.hxx>
-+#include <vcl/graphite_cache.hxx>
-+#include <vcl/graphite_features.hxx>
-+#endif
-+
- #define DROPPED_OUTGLYPH 0xFFFF
- 
- using namespace rtl;
-@@ -1953,11 +1964,25 @@
-     long nDelta = nNewXPos - pVI->mnXOffset;
-     if( nStart > nMinGlyphPos )
-     {
--        // move the glyph by expanding its left glyph
--        int i;
-+        // move the glyph by expanding its left glyph but ignore dropped glyphs
-+        int i, nLastUndropped = nMinGlyphPos - 1;
-         for( i = nMinGlyphPos; i < nStart; ++i )
--            nDelta -= mpGlyphAdvances[ i ];
--        mpGlyphAdvances[ i-1 ] += nDelta;
-+		{
-+			if (mpOutGlyphs[i] != DROPPED_OUTGLYPH)
-+			{
-+	            nDelta -= (mpJustifications)? mpJustifications[ i ] : mpGlyphAdvances[ i ];
-+				nLastUndropped = i;
-+			}
-+		}
-+		if (nLastUndropped >= nMinGlyphPos)
-+		{
-+			mpGlyphAdvances[ nLastUndropped ] += nDelta;
-+			if (mpJustifications) mpJustifications[ nLastUndropped ] += nDelta;
-+		}
-+		else
-+		{
-+			pVI->mnXOffset += nDelta;
-+		}
-     }
-     else
-     {
-@@ -1976,11 +2001,18 @@
-         --nStart;
-     else // if( !nStart )   // nStart==0 for first visible glyph
-     {
--        const VisualItem* pVI = mpVisualItems;
-+        VisualItem* pVI = mpVisualItems;
-         for( int i = mnItemCount, nDummy; --i >= 0; ++pVI )
-             if( GetItemSubrange( *pVI, nStart, nDummy ) )
-                 break;
-         DBG_ASSERT( nStart <= mnGlyphCount, "USPLayout::DropG overflow" );
-+		int nOffset = 0;
-+		int j = pVI->mnMinGlyphPos;
-+		while (mpOutGlyphs[j] == DROPPED_OUTGLYPH) j++;
-+		if (j == nStart)
-+		{
-+			pVI->mnXOffset += ((mpJustifications)? mpJustifications[nStart] : mpGlyphAdvances[nStart]);
-+		}
-     }
- 
-     mpOutGlyphs[ nStart ] = DROPPED_OUTGLYPH;
-@@ -2037,11 +2069,12 @@
-         }
- 
-         // handle dropped glyphs at start of visual item
--        int nEndGlyphPos;
--        GetItemSubrange( rVI, i, nEndGlyphPos );
-+        int nMinGlyphPos, nEndGlyphPos, nOrigMinGlyphPos = rVI.mnMinGlyphPos;
-+        GetItemSubrange( rVI, nMinGlyphPos, nEndGlyphPos );
-+        i = nMinGlyphPos;
-         while( (mpOutGlyphs[i] == cDroppedGlyph) && (i < nEndGlyphPos) )
-         {
--            rVI.mnXOffset += pGlyphWidths[ i ];
-+            //rVI.mnXOffset += pGlyphWidths[ i ];
-             rVI.mnMinGlyphPos = ++i;
-         }
- 
-@@ -2051,6 +2084,17 @@
-             rVI.mnEndGlyphPos = 0;
-             continue;
-         }
-+		// If there are still glyphs in the cluster and mnMinGlyphPos
-+		// has changed then we need to remove the dropped glyphs at start
-+		// to correct logClusters, which is unsigned and relative to the 
-+		// item start.
-+		if (rVI.mnMinGlyphPos != nOrigMinGlyphPos)
-+		{
-+			// drop any glyphs in the visual item outside the range
-+			for (i = nOrigMinGlyphPos; i < nMinGlyphPos; i++)
-+				mpOutGlyphs[ i ] = cDroppedGlyph;
-+			rVI.mnMinGlyphPos = i = nOrigMinGlyphPos;
-+		}
- 
-         // handle dropped glyphs in the middle of visual item
-         for(; i < nEndGlyphPos; ++i )
-@@ -2069,7 +2113,7 @@
-                 mpJustifications[ j ] = mpJustifications[ i ];
-             int k = mpGlyphs2Chars[ i ];
-             mpGlyphs2Chars[ j ]   = k;
--            mpLogClusters[ k ]    = sal::static_int_cast<WORD>(j++);
-+            mpLogClusters[ k ]    = sal::static_int_cast<WORD>(j++) - rVI.mnMinGlyphPos;
-         }
- 
-         rVI.mnEndGlyphPos = j;
-@@ -2473,6 +2517,223 @@
- 
- #endif // USE_UNISCRIBE
- 
-+#ifdef ENABLE_GRAPHITE
-+// This class uses the SIL Graphite engine to provide complex text layout services to the VCL
-+// @author tse
-+//
-+class GraphiteWinLayout : public WinLayout
-+{
-+private:
-+//  GraphiteLayout                                           _layout;
-+    mutable gr::WinFont   mpFont;
-+	grutils::GrFeatureParser * mpFeatures;
-+    mutable GraphiteLayout maImpl;
-+public:
-+    //GraphiteLayout(ServerFont & font, const long xDPI, const long yDPI) throw();
-+    GraphiteWinLayout(HDC hDC, const ImplWinFontData& rWFD, ImplWinFontEntry& rWFE);
-+
-+    //static bool IsGraphiteEnabledFont(ServerFont & font) throw();
-+    static bool IsGraphiteEnabledFont(HDC hDC) throw();
-+
-+    // used by upper layers
-+    virtual bool  LayoutText( ImplLayoutArgs& );    // first step of layout
-+    virtual void  AdjustLayout( ImplLayoutArgs& );  // adjusting after fallback etc.
-+    //  virtual void  InitFont() const;
-+    virtual void  DrawText( SalGraphics& ) const;
-+
-+    // methods using string indexing
-+    virtual int   GetTextBreak( long nMaxWidth, long nCharExtra=0, int nFactor=1 ) const;
-+    virtual long  FillDXArray( long* pDXArray ) const;
-+    virtual void  ApplyDXArray(ImplLayoutArgs &args);
-+
-+    virtual void  GetCaretPositions( int nArraySize, long* pCaretXArray ) const;
-+
-+    // methods using glyph indexing
-+    virtual int   GetNextGlyphs(int nLen, sal_GlyphId* pGlyphIdxAry, ::Point & rPos, int&,
-+                      long* pGlyphAdvAry = 0, int* pCharPosAry = 0 ) const;
-+
-+    // used by glyph+font+script fallback
-+    virtual void    MoveGlyph( int nStart, long nNewXPos );
-+    virtual void    DropGlyph( int nStart );
-+    virtual void    Simplify( bool bIsBase );
-+    ~GraphiteWinLayout() { delete mpFeatures; mpFeatures = NULL; };
-+protected:
-+    virtual void    ReplaceDC(gr::Segment & segment) const;
-+    virtual void    RestoreDC(gr::Segment & segment) const;
-+};
-+
-+bool GraphiteWinLayout::IsGraphiteEnabledFont(HDC hDC) throw()
-+{
-+  return gr::WinFont::FontHasGraphiteTables(hDC);
-+}
-+
-+GraphiteWinLayout::GraphiteWinLayout(HDC hDC, const ImplWinFontData& rWFD, ImplWinFontEntry& rWFE) throw()
-+  : WinLayout(hDC, rWFD, rWFE),
-+	mpFont(hDC),
-+    maImpl(mpFont)
-+{
-+	const rtl::OString aLang = MsLangId::convertLanguageToIsoByteString( rWFE.maFontSelData.meLanguage );
-+	rtl::OString name = rtl::OUStringToOString(
-+        rWFE.maFontSelData.maTargetName, RTL_TEXTENCODING_UTF8 );
-+    sal_Int32 nFeat = name.indexOf(grutils::GrFeatureParser::FEAT_PREFIX) + 1;
-+    if (nFeat > 0)
-+    {
-+        rtl::OString aFeat = name.copy(nFeat, name.getLength() - nFeat);
-+        mpFeatures = new grutils::GrFeatureParser(mpFont, aFeat.getStr(), aLang.getStr());
-+	}
-+	else
-+	{
-+		mpFeatures = new grutils::GrFeatureParser(mpFont, aLang.getStr());
-+	}
-+	maImpl.SetFeatures(mpFeatures);
-+}
-+
-+void GraphiteWinLayout::ReplaceDC(gr::Segment & segment) const
-+{
-+    COLORREF color = GetTextColor(mhDC);
-+    dynamic_cast<gr::WinFont&>(segment.getFont()).replaceDC(mhDC);
-+    SetTextColor(mhDC, color);
-+}
-+
-+void GraphiteWinLayout::RestoreDC(gr::Segment & segment) const
-+{
-+    dynamic_cast<gr::WinFont&>(segment.getFont()).restoreDC();
-+}
-+
-+bool GraphiteWinLayout::LayoutText( ImplLayoutArgs & args)
-+{
-+    HFONT hUnRotatedFont;
-+    if (args.mnOrientation)
-+    {
-+        // Graphite gets very confused if the font is rotated
-+        LOGFONTW aLogFont;
-+        ::GetObjectW( mhFont, sizeof(LOGFONTW), &aLogFont);
-+        aLogFont.lfEscapement = 0;
-+        aLogFont.lfOrientation = 0;
-+        hUnRotatedFont = ::CreateFontIndirectW( &aLogFont);
-+        ::SelectFont(mhDC, hUnRotatedFont);
-+    }
-+    WinLayout::AdjustLayout(args);
-+    mpFont.replaceDC(mhDC);
-+    maImpl.SetFontScale(WinLayout::mfFontScale);
-+    //bool succeeded = maImpl.LayoutText(args);
-+#ifdef GRCACHE
-+    GrSegRecord * pSegRecord = NULL;
-+    gr::Segment * pSegment = maImpl.CreateSegment(args, &pSegRecord);
-+#else
-+    gr::Segment * pSegment = maImpl.CreateSegment(args);
-+#endif
-+    bool bSucceeded = false;
-+    if (pSegment)
-+    {
-+        // replace the DC on the font within the segment
-+        ReplaceDC(*pSegment);
-+        // create glyph vectors
-+#ifdef GRCACHE
-+        bSucceeded = maImpl.LayoutGlyphs(args, pSegment, pSegRecord);
-+#else
-+        bSucceeded = maImpl.LayoutGlyphs(args, pSegment);
-+#endif
-+        // restore original DC
-+        RestoreDC(*pSegment);
-+#ifdef GRCACHE
-+        if (pSegRecord) pSegRecord->unlock();
-+        else delete pSegment;
-+#else
-+        delete pSegment;
-+#endif
-+    }
-+    mpFont.restoreDC();
-+    if (args.mnOrientation)
-+    {
-+        // restore the rotated font
-+        ::SelectFont(mhDC, mhFont);
-+        ::DeleteObject(hUnRotatedFont);
-+    }
-+    return bSucceeded;
-+}
-+
-+void  GraphiteWinLayout::AdjustLayout(ImplLayoutArgs& args)
-+{
-+    WinLayout::AdjustLayout(args);
-+    maImpl.DrawBase() = WinLayout::maDrawBase;
-+    maImpl.DrawOffset() = WinLayout::maDrawOffset;
-+    maImpl.AdjustLayout(args);
-+}
-+
-+void GraphiteWinLayout::DrawText(SalGraphics &sal_graphics) const
-+{
-+    HFONT hOrigFont = DisableFontScaling();
-+    HDC aHDC = static_cast<WinSalGraphics&>(sal_graphics).mhDC;
-+    maImpl.DrawBase() = WinLayout::maDrawBase;
-+    maImpl.DrawOffset() = WinLayout::maDrawOffset;
-+    const int MAX_GLYPHS = 160;
-+    sal_GlyphId glyphIntStr[MAX_GLYPHS];
-+    WORD glyphWStr[MAX_GLYPHS];
-+    int glyphIndex = 0;
-+    Point aPos(0,0);
-+    int nGlyphs = 0;
-+    do
-+    {
-+        nGlyphs = maImpl.GetNextGlyphs(1, glyphIntStr, aPos, glyphIndex);
-+        if (nGlyphs < 1)
-+          break;
-+        std::copy(glyphIntStr, glyphIntStr + nGlyphs, glyphWStr);
-+        ::ExtTextOutW(aHDC, aPos.X(), aPos.Y(), ETO_GLYPH_INDEX,
-+		              NULL, (LPCWSTR)&(glyphWStr), nGlyphs, NULL);
-+    } while (nGlyphs);
-+    if( hOrigFont )
-+          DeleteFont( SelectFont( mhDC, hOrigFont ) );
-+}
-+
-+int GraphiteWinLayout::GetTextBreak( long nMaxWidth, long nCharExtra, int nFactor ) const
-+{
-+    mpFont.replaceDC(mhDC);
-+    int nBreak = maImpl.GetTextBreak(nMaxWidth, nCharExtra, nFactor);
-+    mpFont.restoreDC();
-+    return nBreak;
-+}
-+
-+long  GraphiteWinLayout::FillDXArray( long* pDXArray ) const
-+{
-+    return maImpl.FillDXArray(pDXArray);
-+}
-+
-+void  GraphiteWinLayout::ApplyDXArray(ImplLayoutArgs &args)
-+{
-+    maImpl.DrawBase() = WinLayout::maDrawBase;
-+    maImpl.DrawOffset() = WinLayout::maDrawOffset;
-+    maImpl.ApplyDXArray(args);
-+}
-+
-+void GraphiteWinLayout::GetCaretPositions( int nArraySize, long* pCaretXArray ) const
-+{
-+	maImpl.GetCaretPositions(nArraySize, pCaretXArray);
-+}
-+
-+int GraphiteWinLayout::GetNextGlyphs( int length, sal_GlyphId* glyph_out,
-+        ::Point & pos_out, int &glyph_slot, long * glyph_adv, int *char_index) const
-+{
-+    maImpl.DrawBase() = WinLayout::maDrawBase;
-+    maImpl.DrawOffset() = WinLayout::maDrawOffset;
-+    return maImpl.GetNextGlyphs(length, glyph_out, pos_out, glyph_slot, glyph_adv, char_index);
-+}
-+
-+void GraphiteWinLayout::MoveGlyph( int glyph_idx, long new_x_pos )
-+{
-+	maImpl.MoveGlyph(glyph_idx, new_x_pos);
-+}
-+
-+void GraphiteWinLayout::DropGlyph( int glyph_idx )
-+{
-+	maImpl.DropGlyph(glyph_idx);
-+}
-+
-+void GraphiteWinLayout::Simplify( bool is_base )
-+{
-+	maImpl.Simplify(is_base);
-+}
-+#endif // ENABLE_GRAPHITE
- // =======================================================================
- 
- SalLayout* WinSalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel )
-@@ -2488,6 +2749,11 @@
-     if( !(rArgs.mnFlags & SAL_LAYOUT_COMPLEX_DISABLED)
-     &&   (aUspModule || (bUspEnabled && InitUSP())) )   // CTL layout engine
-     {
-+#ifdef ENABLE_GRAPHITE
-+        if (rFontFace.SupportsGraphite())
-+            pWinLayout = new GraphiteWinLayout(mhDC, rFontFace, rFontInstance);
-+        else
-+#endif // ENABLE_GRAPHITE
-         // script complexity is determined in upper layers
-         pWinLayout = new UniscribeLayout( mhDC, rFontFace, rFontInstance );
-         // NOTE: it must be guaranteed that the WinSalGraphics lives longer than
-@@ -2510,7 +2776,12 @@
-         BYTE eCharSet = ANSI_CHARSET;
-         if( mpLogFont )
-             eCharSet = mpLogFont->lfCharSet;
--        pWinLayout = new SimpleWinLayout( mhDC, eCharSet, rFontFace, rFontInstance );
-+#ifdef ENABLE_GRAPHITE
-+        if (rFontFace.SupportsGraphite())
-+            pWinLayout = new GraphiteWinLayout(mhDC, rFontFace, rFontInstance);
-+        else
-+#endif // ENABLE_GRAPHITE
-+            pWinLayout = new SimpleWinLayout( mhDC, eCharSet, rFontFace, rFontInstance );
-     }
- 
-     if( mfFontScale != 1.0 )
-Index: vcl/win/source/window/MAKEFILE.MK
-===================================================================
---- vcl/win/source/window/MAKEFILE.MK	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/win/source/window/MAKEFILE.MK	(.../cws/graphite01)	(Revision 265804)
-@@ -60,6 +60,10 @@
- EXCEPTIONSFILES=   $(SLO)$/salframe.obj
- .ENDIF
- 
-+.IF "$(ENABLE_GRAPHITE)" == "TRUE"
-+CFLAGS+=-DENABLE_GRAPHITE
-+.ENDIF
-+
- # --- Targets ------------------------------------------------------
- 
- .INCLUDE :	target.mk
-Index: vcl/win/inc/salgdi.h
-===================================================================
---- vcl/win/inc/salgdi.h	(.../tags/DEV300_m35)	(Revision 265804)
-+++ vcl/win/inc/salgdi.h	(.../cws/graphite01)	(Revision 265804)
-@@ -80,6 +80,9 @@
-     bool                    SupportsCJK() const         { return mbHasCJKSupport; }
-     bool                    AliasSymbolsHigh() const    { return mbAliasSymbolsHigh; }
-     bool                    AliasSymbolsLow() const     { return mbAliasSymbolsLow; }
-+#ifdef ENABLE_GRAPHITE
-+	bool                    SupportsGraphite() const    { return mbHasGraphiteSupport; }
-+#endif
- 
-     ImplFontCharMap*        GetImplFontCharMap() const;
-     const Ucs2SIntMap* GetEncodingVector() const { return mpEncodingVector; }
-@@ -96,6 +99,9 @@
-     mutable bool                    mbDisableGlyphApi;
-     mutable bool                    mbHasKoreanRange;
-     mutable bool                    mbHasCJKSupport;
-+#ifdef ENABLE_GRAPHITE
-+	mutable bool                    mbHasGraphiteSupport;
-+#endif
-     mutable ImplFontCharMap*        mpUnicodeMap;
-     mutable const Ucs2SIntMap*      mpEncodingVector;
- 
-Index: drawinglayer/source/processor2d/vclprocessor2d.cxx
-===================================================================
---- drawinglayer/source/processor2d/vclprocessor2d.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ drawinglayer/source/processor2d/vclprocessor2d.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -129,7 +129,7 @@
- 				{
- 					// prepare everything that is not sheared and mirrored
-                     Font aFont(primitive2d::getVclFontFromFontAttributes(
--                        rTextCandidate.getFontAttributes(), aScale.getX(), aScale.getY(), fRotate, *mpOutputDevice));
-+                        rTextCandidate.getFontAttributes(), aScale.getX(), aScale.getY(), fRotate, rTextCandidate.getLocale(), *mpOutputDevice));
- 
- 					// handle additional font attributes
- 					const primitive2d::TextDecoratedPortionPrimitive2D* pTCPP =
-Index: drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx
-===================================================================
---- drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -92,7 +92,7 @@
- 
-                 // TextLayouterDevice is needed to get metrics for text decorations like 
-                 // underline/strikeout/emphasis marks from it. For setup, the font size is needed
--			    aTextLayouter.setFontAttributes(getFontAttributes(), rDecTrans.getScale().getX(), rDecTrans.getScale().getY());
-+			    aTextLayouter.setFontAttributes(getFontAttributes(), rDecTrans.getScale().getX(), rDecTrans.getScale().getY(), getLocale());
- 
- 				// get text width
- 				double fTextWidth(0.0);
-Index: drawinglayer/source/primitive2d/textlayoutdevice.cxx
-===================================================================
---- drawinglayer/source/primitive2d/textlayoutdevice.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ drawinglayer/source/primitive2d/textlayoutdevice.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -41,6 +41,7 @@
- #include <vcl/virdev.hxx>
- #include <vcl/font.hxx>
- #include <vcl/metric.hxx>
-+#include <i18npool/mslangid.hxx>
- #include <drawinglayer/primitive2d/textprimitive2d.hxx>
- 
- //////////////////////////////////////////////////////////////////////////////
-@@ -165,14 +166,14 @@
- 			mrDevice.SetFont( rFont );
- 		}
- 
--		void TextLayouterDevice::setFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DHomMatrix& rTransform)
-+		void TextLayouterDevice::setFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DHomMatrix& rTransform, const ::com::sun::star::lang::Locale & rLocale)
- 		{
--			setFont(getVclFontFromFontAttributes(rFontAttributes, rTransform, mrDevice));
-+			setFont(getVclFontFromFontAttributes(rFontAttributes, rTransform, rLocale, mrDevice));
- 		}
- 
--		void TextLayouterDevice::setFontAttributes(const FontAttributes& rFontAttributes, double fFontScaleX, double fFontScaleY)
-+		void TextLayouterDevice::setFontAttributes(const FontAttributes& rFontAttributes, double fFontScaleX, double fFontScaleY, const ::com::sun::star::lang::Locale & rLocale)
- 		{
--			setFont(getVclFontFromFontAttributes(rFontAttributes, fFontScaleX, fFontScaleY, 0.0, mrDevice));
-+			setFont(getVclFontFromFontAttributes(rFontAttributes, fFontScaleX, fFontScaleY, 0.0, rLocale, mrDevice));
-         }
- 
- 		double TextLayouterDevice::getUnderlineOffset() const
-@@ -262,6 +263,7 @@
- 		Font getVclFontFromFontAttributes(
-             const FontAttributes& rFontAttributes, 
-             const basegfx::B2DHomMatrix& rTransform,
-+            const ::com::sun::star::lang::Locale & rLocale,
-             const OutputDevice& rOutDev)
- 		{
- 			// decompose matrix to have position and size of text
-@@ -270,7 +272,7 @@
- 			
-             rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
-             
--            return getVclFontFromFontAttributes(rFontAttributes, aScale.getX(), aScale.getY(), fRotate, rOutDev);
-+            return getVclFontFromFontAttributes(rFontAttributes, aScale.getX(), aScale.getY(), fRotate, rLocale, rOutDev);
- 		}
- 
- 		Font getVclFontFromFontAttributes(
-@@ -278,6 +280,7 @@
-             double fFontScaleX, 
-             double fFontScaleY, 
-             double fFontRotation,
-+            const ::com::sun::star::lang::Locale & rLocale,
-             const OutputDevice& /*rOutDev*/)
- 		{
- 			sal_uInt32 nWidth(basegfx::fround(fabs(fFontScaleX)));
-@@ -297,6 +300,7 @@
- 			aRetval.SetWeight(static_cast<FontWeight>(rFontAttributes.getWeight()));
- 			aRetval.SetItalic(rFontAttributes.getItalic() ? ITALIC_NORMAL : ITALIC_NONE);
- 			aRetval.SetOutline(rFontAttributes.getOutline());
-+            aRetval.SetLanguage(MsLangId::convertLocaleToLanguage(rLocale));
- 
- #ifdef WIN32
-             if(nWidth != nHeight)
-Index: drawinglayer/source/primitive2d/textprimitive2d.cxx
-===================================================================
---- drawinglayer/source/primitive2d/textprimitive2d.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ drawinglayer/source/primitive2d/textprimitive2d.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -142,7 +142,7 @@
- 
- 					// prepare textlayoutdevice
- 					TextLayouterDevice aTextLayouter;
--					aTextLayouter.setFontAttributes(getFontAttributes(), aFontScale.getX(), aFontScale.getY());
-+					aTextLayouter.setFontAttributes(getFontAttributes(), aFontScale.getX(), aFontScale.getY(), getLocale());
- 	                
- 					// get the text outlines. No DXArray is given (would contain integers equal to unit vector
- 					// transformed by object's transformation), let VCL do the job
-@@ -289,7 +289,7 @@
- 
- 					// prepare textlayoutdevice
- 					TextLayouterDevice aTextLayouter;
--					aTextLayouter.setFontAttributes(getFontAttributes(), aFontScale.getX(), aFontScale.getY());
-+					aTextLayouter.setFontAttributes(getFontAttributes(), aFontScale.getX(), aFontScale.getY(), getLocale());
- 
- 					// get basic text range
- 					aRetval = aTextLayouter.getTextBoundRect(getText(), getTextPosition(), getTextLength());
-Index: drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx
-===================================================================
---- drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx	(.../cws/graphite01)	(Revision 265804)
-@@ -41,6 +41,7 @@
- #include <tools/poly.hxx>
- #include <basegfx/range/b2drange.hxx>
- #include <vector>
-+#include <com/sun/star/lang/Locale.hpp>
- 
- //////////////////////////////////////////////////////////////////////////////
- // predefines
-@@ -75,8 +76,8 @@
- 			~TextLayouterDevice();
- 			
- 			void setFont(const Font& rFont);
--			void setFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DHomMatrix& rTransform);
--			void setFontAttributes(const FontAttributes& rFontAttributes, double fFontScaleX, double fFontScaleY);
-+			void setFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DHomMatrix& rTransform, const ::com::sun::star::lang::Locale & rLocale);
-+			void setFontAttributes(const FontAttributes& rFontAttributes, double fFontScaleX, double fFontScaleY, const ::com::sun::star::lang::Locale & rLocale);
- 
- 			double getTextHeight() const;
- 			double getUnderlineHeight() const;
-@@ -113,12 +114,14 @@
-             const FontAttributes& rFontAttributes, 
-             double fFontScaleX, 
-             double fFontScaleY,
--            double fFontRotation, 
-+            double fFontRotation,
-+            const ::com::sun::star::lang::Locale & rLocale,
-             const OutputDevice& rOutDev);
- 		
-         Font getVclFontFromFontAttributes(
-             const FontAttributes& rFontAttributes, 
-             const basegfx::B2DHomMatrix& rTransform,
-+            const ::com::sun::star::lang::Locale & rLocale,
-             const OutputDevice& rOutDev);
- 		
-         FontAttributes getFontAttributesFromVclFont(basegfx::B2DVector& rSize, const Font& rFont, bool bRTL, bool bBiDiStrong);
-Index: drawinglayer/util/makefile.mk
-===================================================================
---- drawinglayer/util/makefile.mk	(.../tags/DEV300_m35)	(Revision 265804)
-+++ drawinglayer/util/makefile.mk	(.../cws/graphite01)	(Revision 265804)
-@@ -72,6 +72,7 @@
- 		$(CPPUHELPERLIB)	\
- 		$(CPPULIB)			\
- 		$(AVMEDIALIB)		\
-+		$(I18NISOLANGLIB)	\
- 		$(COMPHELPERLIB)
- 
- SHL1DEF=	$(MISC)$/$(SHL1TARGET).def
-Index: sc/source/core/data/patattr.cxx
-===================================================================
---- sc/source/core/data/patattr.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ sc/source/core/data/patattr.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -257,14 +257,16 @@
- 	FontEmphasisMark eEmphasis;
- 	FontRelief eRelief;
- 	Color aColor;
-+	LanguageType eLang;
- 
--	USHORT nFontId, nHeightId, nWeightId, nPostureId;
-+	USHORT nFontId, nHeightId, nWeightId, nPostureId, nLangId;
- 	if ( nScript == SCRIPTTYPE_ASIAN )
- 	{
- 		nFontId    = ATTR_CJK_FONT;
- 		nHeightId  = ATTR_CJK_FONT_HEIGHT;
- 		nWeightId  = ATTR_CJK_FONT_WEIGHT;
- 		nPostureId = ATTR_CJK_FONT_POSTURE;
-+		nLangId    = ATTR_CJK_FONT_LANGUAGE;
- 	}
- 	else if ( nScript == SCRIPTTYPE_COMPLEX )
- 	{
-@@ -272,6 +274,7 @@
- 		nHeightId  = ATTR_CTL_FONT_HEIGHT;
- 		nWeightId  = ATTR_CTL_FONT_WEIGHT;
- 		nPostureId = ATTR_CTL_FONT_POSTURE;
-+		nLangId    = ATTR_CTL_FONT_LANGUAGE;
- 	}
- 	else
- 	{
-@@ -279,6 +282,7 @@
- 		nHeightId  = ATTR_FONT_HEIGHT;
- 		nWeightId  = ATTR_FONT_WEIGHT;
- 		nPostureId = ATTR_FONT_POSTURE;
-+		nLangId    = ATTR_FONT_LANGUAGE;
- 	}
- 
- 	if ( pCondSet )
-@@ -332,6 +336,10 @@
- 		if ( pCondSet->GetItemState( ATTR_FONT_COLOR, TRUE, &pItem ) != SFX_ITEM_SET )
-             pItem = &rItemSet.Get( ATTR_FONT_COLOR );
- 		aColor = ((const SvxColorItem*)pItem)->GetValue();
-+
-+		if ( pCondSet->GetItemState( nLangId, TRUE, &pItem ) != SFX_ITEM_SET )
-+			pItem = &rItemSet.Get( nLangId );
-+		eLang = ((const SvxLanguageItem*)pItem)->GetLanguage();
- 	}
-     else    // alles aus rItemSet
- 	{
-@@ -358,6 +366,9 @@
-                         rItemSet.Get( ATTR_FONT_RELIEF )).GetValue();
- 		aColor = ((const SvxColorItem&)
-                         rItemSet.Get( ATTR_FONT_COLOR )).GetValue();
-+		// for graphite language features
-+		eLang =
-+		((const SvxLanguageItem&)rItemSet.Get( nLangId )).GetLanguage();
- 	}
- 	DBG_ASSERT(pFontAttr,"nanu?");
- 
-@@ -374,6 +385,8 @@
- 	rFont.SetCharSet( pFontAttr->GetCharSet() );
- 	rFont.SetPitch( pFontAttr->GetPitch() );
- 
-+	rFont.SetLanguage(eLang);
-+
- 	//	Groesse
-
- 
-
-Index: configure.in
-===================================================================
---- configure.in	(.../tags/DEV300_m35)	(Revision 265804)
-+++ configure.in	(.../cws/graphite01)	(Revision 265804)
-@@ -29,6 +29,12 @@
- [  --without-gpc           Use the internal polygon clipping code instead of
-                           the external GPC polygon clipping library.
- ],,if test ! -e ../external/gpc/gpc.c && test ! -e ../external/gpc/gpc.h; then without_gpc=yes; fi)
-+AC_ARG_ENABLE(graphite,
-+[  --enable-graphite       Enables the compilation of Graphite smart font rendering
-+],,)
-+AC_ARG_WITH(system-graphite,
-+[  --with-system-graphite    use graphite library already installed on system
-+],,)
- AC_ARG_ENABLE(mono,
- [  --enable-mono           Enables the compilation of the Mono bindings
- ],,)
-@@ -4234,6 +4240,39 @@
- AC_SUBST(SYSTEM_GENCMN)
- 
- dnl ===================================================================
-+dnl Graphite
-+dnl ===================================================================
-+
-+AC_MSG_CHECKING([whether to enable graphite support])
-+if test "z$enable_graphite" != "z" -a "$enable_graphite" != "no" ; then
-+    AC_MSG_RESULT([yes])
-+    ENABLE_GRAPHITE="TRUE"
-+    AC_MSG_CHECKING([which graphite to use])
-+    if test -n "$with_system_graphite" -o -n "$with_system_libs" && \
-+        test "$with_system_graphite" != "no"; then
-+        AC_MSG_RESULT([external])
-+        SYSTEM_GRAPHITE=YES
-+        PKG_CHECK_MODULES( GRAPHITE, silgraphite )
-+	AC_MSG_CHECKING([STL compatibility])
-+	if test "$WITH_STLPORT" != "no"; then
-+		AC_MSG_ERROR([to use system graphite you need to use --without-stlport])
-+	else
-+		AC_MSG_RESULT([OK])	
-+	fi
-+    else
-+        AC_MSG_RESULT([internal])
-+        SYSTEM_GRAPHITE=NO
-+        BUILD_TYPE="$BUILD_TYPE GRAPHITE"
-+    fi
-+else
-+   AC_MSG_RESULT([no])
-+fi
-+AC_SUBST(ENABLE_GRAPHITE)
-+AC_SUBST(SYSTEM_GRAPHITE)
-+AC_SUBST(GRAPHITE_LIBS)
-+AC_SUBST(GRAPHITE_CFLAGS)
-+
-+dnl ===================================================================
- dnl Checks for libraries.
- dnl ===================================================================
- dnl Check for Mac OS X native GUI, which may be used instead of X11.
-Index: set_soenv.in
-===================================================================
---- set_soenv.in	(.../tags/DEV300_m35)	(Revision 265804)
-+++ set_soenv.in	(.../cws/graphite01)	(Revision 265804)
-@@ -1887,6 +1887,10 @@
- ToFile( "ENABLE_DIRECTX",    "@ENABLE_DIRECTX@",    "e" );
- ToFile( "ENABLE_LAYOUT",     "@ENABLE_LAYOUT@",     "e" );
- ToFile( "ENABLE_PCH",        "@ENABLE_PCH@",       "e" );
-+ToFile( "ENABLE_GRAPHITE",   "@ENABLE_GRAPHITE@",   "e");
-+ToFile( "SYSTEM_GRAPHITE",   "@SYSTEM_GRAPHITE@",   "e");
-+ToFile( "GRAPHITE_LIBS",     "@GRAPHITE_LIBS@",     "e");
-+ToFile( "GRAPHITE_CFLAGS",   "@GRAPHITE_CFLAGS@",   "e");
- ToFile( "VC_STANDARD",       "@VC_STANDARD@",      "e" );
- ToFile( "WITH_GPC",          "@WITH_GPC@",         "e" );
- ToFile( "WITH_MYSPELL_DICTS","@WITH_MYSPELL_DICTS@","e");
-Index: sw/source/core/text/itrform2.cxx
-===================================================================
---- sw/source/core/text/itrform2.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ sw/source/core/text/itrform2.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -1973,6 +1973,7 @@
-         nReformat -= 2;
- 
- #ifndef QUARTZ
-+#ifndef ENABLE_GRAPHITE
-         // --> FME 2004-09-27 #i28795#, #i34607#, #i38388#
-         // step back six(!) more characters for complex scripts
-         // this is required e.g., for Khmer (thank you, Javier!)
-@@ -1981,6 +1982,10 @@
-         if( ::i18n::ScriptType::COMPLEX == rSI.ScriptType( nReformat ) )
-             nMaxContext = 6;
- #else
-+        // Some Graphite fonts need context for scripts not marked as complex
-+        static const xub_StrLen nMaxContext = 10;
-+#endif
-+#else
-         // some fonts like Quartz's Zapfino need more context
-         // TODO: query FontInfo for maximum unicode context
-         static const xub_StrLen nMaxContext = 8;
-Index: sw/source/core/text/makefile.mk
-===================================================================
---- sw/source/core/text/makefile.mk	(.../tags/DEV300_m35)	(Revision 265804)
-+++ sw/source/core/text/makefile.mk	(.../cws/graphite01)	(Revision 265804)
-@@ -45,6 +45,9 @@
- CDEFS+=-Dmydebug
- .ENDIF
- 
-+.IF "$(ENABLE_GRAPHITE)" == "TRUE"
-+CFLAGS+=-DENABLE_GRAPHITE
-+.ENDIF
- # --- Files --------------------------------------------------------
- 
- .IF "$(product)$(cap)" == ""
-Index: sw/source/core/text/porlay.cxx
-===================================================================
---- sw/source/core/text/porlay.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ sw/source/core/text/porlay.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -45,6 +45,7 @@
- #include <porrst.hxx>		// SwHangingPortion
- #include <pormulti.hxx> 	// SwMultiPortion
- #include <breakit.hxx>
-+#include <unicode/uchar.h>
- #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
- #include <com/sun/star/i18n/ScriptType.hdl>
- #endif
-@@ -986,7 +987,26 @@
-         if ( nChg > rTxt.Len() )
-             nChg = rTxt.Len();
- 
--        aScriptChg.Insert( nChg, nCnt );
-+        // special case for dotted circle since it can be used with complex
-+        // before a mark, so we want it associated with the mark's script
-+        if (nChg < rTxt.Len() && nChg > 0 && (i18n::ScriptType::WEAK ==
-+            pBreakIt->xBreak->getScriptType(rTxt,nChg - 1)))
-+        {
-+            int8_t nType = u_charType(rTxt.GetChar(nChg) );
-+            if (nType == U_NON_SPACING_MARK || nType == U_ENCLOSING_MARK ||
-+                nType == U_COMBINING_SPACING_MARK )
-+            {
-+                aScriptChg.Insert( nChg - 1, nCnt );
-+            }
-+            else
-+            {
-+                aScriptChg.Insert( nChg, nCnt );
-+            }
-+        }
-+        else
-+        {
-+            aScriptChg.Insert( nChg, nCnt );
-+        }
-         aScriptType.Insert( nScript, nCnt++ );
- 
-         // if current script is asian, we search for compressable characters
-Index: sw/source/core/txtnode/fntcache.cxx
-===================================================================
---- sw/source/core/txtnode/fntcache.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ sw/source/core/txtnode/fntcache.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -177,6 +177,7 @@
- 	bPaintBlank = ( UNDERLINE_NONE != aFont.GetUnderline()
- 				  || STRIKEOUT_NONE != aFont.GetStrikeout() )
- 				  && !aFont.IsWordLineMode();
-+	aFont.SetLanguage(rFont.GetLanguage());
- }
- 
- SwFntObj::~SwFntObj()
-Index: sw/source/core/bastyp/breakit.cxx
-===================================================================
---- sw/source/core/bastyp/breakit.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ sw/source/core/bastyp/breakit.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -32,6 +32,7 @@
- #include "precompiled_sw.hxx"
- 
- #include "breakit.hxx"
-+#include <unicode/uchar.h>
- #include <com/sun/star/lang/XMultiServiceFactory.hpp>
- #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
- #include <com/sun/star/i18n/ScriptType.hdl>
-@@ -114,6 +115,18 @@
- 			--nPos;
- 		nScript = xBreak->getScriptType( rTxt, nPos );
- 		sal_Int32 nChgPos = 0;
-+        if ( i18n::ScriptType::WEAK == nScript && nPos + 1 < rTxt.Len() )
-+        {
-+            // A weak character followed by a mark may be meant to combine with
-+            // the mark, so prefer the following character's script
-+            switch ( u_charType(rTxt.GetChar(nPos + 1) ) ) {
-+            case U_NON_SPACING_MARK:
-+            case U_ENCLOSING_MARK:
-+            case U_COMBINING_SPACING_MARK:
-+                nScript = xBreak->getScriptType( rTxt, nPos+1 );
-+                break;
-+            }
-+        }
-         if( i18n::ScriptType::WEAK == nScript && nPos &&
- 			0 < (nChgPos = xBreak->beginOfScript( rTxt, nPos, nScript )) )
- 			nScript = xBreak->getScriptType( rTxt, nChgPos-1 );
-Index: graphite/graphite-2.3.patch
-===================================================================
---- graphite/graphite-2.3.patch	(.../tags/DEV300_m35)	(Revision 0)
-+++ graphite/graphite-2.3.patch	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,358 @@
-+--- misc/build/silgraphite-2.3/engine/include/graphite/GrCommon.h	2007-12-20 12:51:13.000000000 +0000
-++++ misc/build/silgraphite-2.3/engine/include/graphite/GrCommon.h	2007-12-20 12:50:53.000000000 +0000
-+@@ -41,7 +41,7 @@
-+ // Provided the client includes GrClient.h first this #define is
-+ // picked up by all files.
-+ 
-+-//#define gr gr2
-++#define gr gr3ooo
-+ 
-+ // Project headers
-+ #include "GrPlatform.h"
-+
-+
-+--- misc/build/silgraphite-2.3/wrappers/win32/WinFont.h	2008-02-06 19:20:23.437500000 +0000
-++++ misc/build/silgraphite-2.3/wrappers/win32/WinFont.h	2008-02-06 19:25:01.406250000 +0000
-+@@ -27,6 +27,10 @@
-+ #include "GrClient.h"
-+ #include "Font.h"
-+ 
-++#ifdef _STLPORT_VERSION
-++namespace stdext = std;
-++#endif
-++
-+ namespace gr
-+ {
-+ 
-+--- misc/build/silgraphite-2.3/engine/src/segment/GrTableManager.cpp	2008-02-06 19:32:56.015625000 +0000
-++++ misc/build/silgraphite-2.3/engine/src/segment/GrTableManager.cpp	2008-02-06 19:33:09.734375000 +0000
-+@@ -25,8 +25,8 @@
-+ DEFINE_THIS_FILE
-+ #ifndef _WIN32
-+ #include <stdlib.h>
-+-#include <math.h>
-+ #endif
-++#include <math.h>
-+ 
-+ //:>********************************************************************************************
-+ //:>	Forward declarations
-+--- misc/build/silgraphite-2.3/engine/src/segment/GrEngine.cpp	2008-01-31 17:02:28.000000000 +0000
-++++ misc/build/silgraphite-2.3/engine/src/segment/GrEngine.cpp	2008-02-07 22:44:00.875000000 +0000
-+@@ -158,12 +158,12 @@
-+ GrEngine::~GrEngine()
-+ {
-+ 	DestroyEverything();
-+-	#ifdef _MSC_VER
-+-	if (!_CrtCheckMemory())
-+-	{
-+-		OutputDebugString(L"bad memory");
-+-	}
-+-	#endif
-++//	#ifdef _MSC_VER
-++//	if (!_CrtCheckMemory())
-++//	{
-++//		OutputDebugString(L"bad memory");
-++//	}
-++//	#endif
-+ }
-+ 
-+ /*----------------------------------------------------------------------------------------------
-+@@ -172,12 +172,12 @@
-+ void GrEngine::DestroyEverything()
-+ {
-+ 	DestroyContents();
-+-	#ifdef _MSC_VER
-+-	if (!_CrtCheckMemory())
-+-	{
-+-		OutputDebugString(L"bad memory");
-+-	}
-+-	#endif
-++//	#ifdef _MSC_VER
-++//	if (!_CrtCheckMemory())
-++//	{
-++//		OutputDebugString(L"bad memory");
-++//	}
-++//	#endif
-+ 
-+ 	m_strCtrlFileReg.erase();
-+ 	m_strCtrlFileBold.erase();
-+--- misc/build/silgraphite-2.3/wrappers/win32/WinFont.cpp	2008-01-31 17:02:28.000000000 +0000
-++++ misc/build/silgraphite-2.3/wrappers/win32/WinFont.cpp	2008-02-14 20:51:20.937500000 +0000
-+@@ -219,7 +219,12 @@
-+ ----------------------------------------------------------------------------------------------*/
-+ bool WinFont::FontHasGraphiteTables(HDC hdc)
-+ {
-+-	DWORD cbTableSz = ::GetFontData(hdc, kttiSilf, 0, NULL, 0);
-++	fontTableId32 tableID = kttiSilf;
-++	fontTableId32 tableIdBIG  = (tableID & 0x000000FF) << 24;
-++	              tableIdBIG += (tableID & 0x0000FF00) << 8;
-++	              tableIdBIG += (tableID & 0x00FF0000) >> 8;
-++	              tableIdBIG += (tableID & 0xFF000000) >> 24;
-++	DWORD cbTableSz = ::GetFontData(hdc, tableIdBIG, 0, NULL, 0);
-+ 	if (cbTableSz == GDI_ERROR)
-+ 		return false;
-+ 	else if (cbTableSz == 0)
-+--- misc/build/silgraphite-2.3/engine/makefile.vc	2008-01-31 17:02:28.000000000 +0000
-++++ misc/build/silgraphite-2.3/engine/makefile.vc	2008-03-07 18:46:55.015625000 +0000
-+@@ -1,8 +1,14 @@
-+ 
-+ TARGET=graphite
-+ 
-++!IF "$(COMEX)" == "11"
-++WCHAR=/Zc:wchar_t-
-++!ELSE
-++WCHAR=
-++!ENDIF
-++
-+ CPP=cl.exe
-+-CPPFLAGS=/nologo /W4 /GR /GX /I "./src/font" /I "./src/painter" /I "./src/segment" /I "./src/textsource" /I "./src/generic" /I "./include/graphite" /I "../wrappers/win32" /D "GR_NAMESPACE" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "TRACING"  /Fp"$(INTDIR)\graphite.pch" /YX /Fd"$(INTDIR)\\" /FD /c
-++CPPFLAGS=/nologo /W4 /GR /EHsc /I "./src/font" /I "./src/painter" /I "./src/segment" /I "./src/textsource" /I "./src/generic" /I "./include/graphite" /I "../wrappers/win32" /D "GR_NAMESPACE" /D "WIN32" /D "_WINDOWS" /D "_UNICODE" /D "UNICODE" /D "TRACING"  /Fp"$(INTDIR)\graphite.pch" /Fd"$(INTDIR)\\" /FD /c $(WCHAR)
-+ 
-+ LINK=link.exe
-+ LINK_FLAGS=kernel32.lib user32.lib gdi32.lib winspool.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib /nologo /dll /pdb:"$(OUTDIR)\\graphite.pdb" /machine:I386 /out:"$(OUTDIR)\\$(TARGET).dll" /implib:"$(OUTDIR)\\$(TARGET).lib"
-+--- misc/build/silgraphite-2.3/engine/configure.ac~	2008-01-15 10:57:55.000000000 +0000
-++++ misc/build/silgraphite-2.3/engine/configure.ac	2008-03-25 14:51:35.000000000 +0000
-+@@ -56,7 +56,7 @@
-+ # Enable debug
-+ build_flags=""
-+ if test "$enable_debug" = yes; then
-+-  build_flags="$build_flags -O0 -g -Wall -Wno-unknown-pragmas -Wparentheses -Werror"
-++  build_flags="$build_flags -O0 -g -Wall -Wno-unknown-pragmas -Wparentheses"
-+ else
-+   build_flags="$build_flags -DNDEBUG"
-+ fi
-+--- misc/build/silgraphite-2.3/engine/src/segment/Segment.cpp~	2008-01-30 09:36:46.000000000 +0000
-++++ misc/build/silgraphite-2.3/engine/src/segment/Segment.cpp	2008-03-27 11:15:43.000000000 +0000
-+@@ -1363,7 +1363,7 @@
-+ 		ichTry++;
-+ 	}
-+ 
-+-	if (ichTry >= m_ichwMin + m_dichwLim)
-++	if (ichBestBreak > -1 && ichTry >= m_ichwMin + m_dichwLim)
-+ 	{
-+ 		// Break at the end of the segment.
-+ 		ichBreak = m_ichwMin + m_dichwLim;
-+--- misc/build/silgraphite-2.3/engine/include/graphite/Segment.h	2007-11-24 20:37:07.000000000 +0700
-++++ misc/build/silgraphite-2.3/engine/include/graphite/Segment.h	2008-07-07 11:13:40.000000000 +0700
-+@@ -203,7 +203,7 @@
-+ //		m_psegNext = psegNext;
-+ //	}
-+ 
-+-	void SetFaceName(std::wstring stu, std::wstring stuBase)
-++	void SetFaceName(std::wstring /*stu*/, std::wstring /*stuBase*/)
-+ 	{
-+ //		m_stuFaceName = stu;
-+ //		m_stuBaseFaceName = stuBase;
-+--- misc/build/silgraphite-2.3/engine/include/graphite/SegmentPainter.h	2008-01-10 14:41:13.000000000 +0700
-++++ misc/build/silgraphite-2.3/engine/include/graphite/SegmentPainter.h	2008-07-07 11:16:17.000000000 +0700
-+@@ -53,8 +53,8 @@
-+ 	virtual void setPosition(float xdPosition, float ydPosition);
-+     virtual void setScalingFactors(float xFactor, float yFactor);
-+ 
-+-	virtual void setBuggyDisplayFormat(int strategy, long textColor, long backColor,
-+-		long underlineColor)
-++	virtual void setBuggyDisplayFormat(int /*strategy*/, long /*textColor*/, long /*backColor*/,
-++		long /*underlineColor*/)
-+ 	{
-+ 		// Currently not implemented to do anything useful.
-+ 	}
-+@@ -197,7 +197,7 @@
-+ 
-+ 	// Low-level routines--these must be implemented appropriate by subclasses:
-+ 
-+-	virtual void InvertRect(float xLeft, float yTop, float xRight, float yBottom)
-++	virtual void InvertRect(float /*xLeft*/, float /*yTop*/, float /*xRight*/, float /*yBottom*/)
-+ 	{
-+ 		GrAssert(false); // no device context
-+ 	}
-+
-+--- misc/build/silgraphite-2.3/engine/src/segment/GrSlotStream.cpp.orig	2007-11-24 13:37:08.000000000 +0000
-++++ misc/build/silgraphite-2.3/engine/src/segment/GrSlotStream.cpp	2008-08-28 19:48:22.796875000 +0100
-+@@ -1094,6 +1094,7 @@
-+ 	case kdircLRO:
-+ 	case kdircLRE:
-+ 	case kdircPdfL:
-++	case kdircLlb:
-+ 		return false;
-+ 
-+ 	case kdircR:
-+@@ -1103,9 +1104,17 @@
-+ 	case kdircRLO:
-+ 	case kdircRLE:
-+ 	case kdircPdfR:
-++	case kdircRlb:
-+ 		return true;
-+ 
-+ 	case kdircNeutral:
-++	case kdircWhiteSpace:
-++	case kdircComSep:
-++	case kdircEuroSep:
-++	case kdircEuroTerm:
-++	case kdircBndNeutral:
-++	case kdircNSM:
-++	case kdircPDF:
-+ 		return false;
-+ 
-+ 	default:
-+@@ -1970,7 +1979,12 @@
-+ 	while (m_vislotNextChunkMap[islotRet] == -1 && islotRet < m_islotReadPos)
-+ 	{
-+ 		++islotRet;
-+-		Assert(islotRet < signed(m_vislotNextChunkMap.size()));
-++		//Assert(islotRet < signed(m_vislotNextChunkMap.size()));
-++       if (islotRet >= signed(m_vislotNextChunkMap.size()))
-++ 		{
-++ 			islotRet = m_vislotNextChunkMap.size() - 1;
-++ 			break;
-++ 		}
-+ 	}
-+ 	return islotRet;
-+ }
-+--- misc/build/silgraphite-2.3/wrappers/win32/WinFont.cpp.orig	2008-09-27 19:58:12.937500000 +0630
-++++ misc/build/silgraphite-2.3/wrappers/win32/WinFont.cpp	2008-09-27 21:10:26.187500000 +0630
-+@@ -722,6 +722,7 @@
-+ WinFont::FontHandleCache::~FontHandleCache()
-+ {
-+ 	ResetFontCache();
-++	m_bValid = false;
-+ }
-+ 
-+ /*----------------------------------------------------------------------------------------------
-+@@ -767,7 +768,7 @@
-+ ----------------------------------------------------------------------------------------------*/
-+ void WinFont::FontHandleCache::DeleteFont(HFONT hfont)
-+ {
-+-	if (!hfont)
-++	if (!hfont || !m_bValid)
-+ 		return;
-+ 
-+ 	// find the font in the hash map
-+@@ -782,7 +782,7 @@
-+ 			{
-+ 				// delete font
-+ 				::DeleteObject(hfont);
-+-				m_hmlffcv.erase(it->first);
-++				m_hmlffcv.erase(it);
-+ 			}
-+ 			else
-+ 			{
-+--- misc/build/silgraphite-2.3/wrappers/win32/WinFont.h.orig	2008-09-29 10:14:03.453125000 +0630
-++++ misc/build/silgraphite-2.3/wrappers/win32/WinFont.h	2008-09-29 10:16:33.093750000 +0630
-+@@ -199,7 +199,7 @@
-+ 				return (hfont == val.hfont);
-+ 			}
-+ 		};
-+-
-++		FontHandleCache() : m_bValid(true) {};
-+ 		~FontHandleCache();
-+ 
-+ 		HFONT GetFont(LOGFONT & lf);
-+@@ -209,7 +209,7 @@
-+ 
-+ 	protected:
-+ 		FontHandleHashMap m_hmlffcv;
-+-
-++		bool m_bValid;
-+ 		void ResetFontCache(); // delete all the fonts in the cache
-+ 	};
-+ 
-+--- misc/build/silgraphite-2.3/engine/test/RegressionTest/main.h~	2007-04-05 07:23:53.000000000 +0700
-++++ misc/build/silgraphite-2.3/engine/test/RegressionTest/main.h	2008-11-13 01:53:34.000000000 +0700
-+@@ -34,7 +34,8 @@
-+ #include <iostream>
-+ #include <vector>
-+ ////#include <algorithm>
-+-#include <string>
-++#include <string>
-++#include <cstring>
-+ #ifdef _WIN32
-+ #include <crtdbg.h>
-+ #endif // _WIN32
-+ 
-+--- misc/build/silgraphite-2.3/engine/src/font/TtfUtil.cpp.orig	2008-11-13 02:03:45.000000000 +0700
-++++ misc/build/silgraphite-2.3/engine/src/font/TtfUtil.cpp	2008-11-13 02:04:18.000000000 +0700
-+@@ -21,6 +21,8 @@
-+ #include <algorithm>
-+ #include <cassert>
-+ #include <cstddef>
-++#include <limits.h>
-++#include <cstring>
-+ #include <stdexcept>
-+ // Platform headers
-+ // Module headers
-+@@ -583,9 +585,9 @@
-+ 			bool fNameFound = false;
-+ 			int nLangId = read(pRecord->language_id);
-+ 			int nNameId = read(pRecord->name_id);
-+-			for (int i = 0; i < cNameIds; i++)
-++			for (int j = 0; j < cNameIds; j++)
-+ 			{
-+-				if (nNameId == nameIdList[i])
-++				if (nNameId == nameIdList[j])
-+ 				{
-+ 					fNameFound = true;
-+ 					break;
-+--- misc/build/silgraphite-2.3/engine/src/segment/GrEngine.cpp.orig	2008-11-13 02:08:13.000000000 +0700
-++++ misc/build/silgraphite-2.3/engine/src/segment/GrEngine.cpp	2008-11-13 02:08:36.000000000 +0700
-+@@ -15,6 +15,7 @@
-+ //:>	   Include files
-+ //:>********************************************************************************************
-+ #include "Main.h"
-++#include <cstring>
-+ #include <functional>
-+ #ifdef _MSC_VER
-+ #pragma hdrstop
-+--- misc/build/silgraphite-2.3/engine/src/segment/Main.h~	2007-11-24 20:37:08.000000000 +0700
-++++ misc/build/silgraphite-2.3/engine/src/segment/Main.h	2008-11-13 02:14:56.000000000 +0700
-+@@ -51,6 +51,7 @@
-+ #include <vector>
-+ ////#include <algorithm>
-+ #include <string>
-++#include <cstring>
-+ 
-+ // gAssert should be used for any kind of assertions that can be caused by a corrupted font,
-+ // particularly those that won't be caught when loading the tables.
-+--- misc/build/silgraphite-2.3/engine/test/ProfileHarness/ProfileHarness.cpp.orig	2008-11-13 02:23:37.000000000 +0700
-++++ misc/build/silgraphite-2.3/engine/test/ProfileHarness/ProfileHarness.cpp	2008-11-13 02:25:13.000000000 +0700
-+@@ -22,6 +22,7 @@
-+ #include <iomanip>
-+ #include <string>
-+ #include <sstream>
-++#include <cstring>
-+ 
-+ #include <graphite/GrClient.h>
-+ #include <graphite/ITextSource.h>
-+--- misc/build/silgraphite-2.3/engine/makefile.vc.orig	2008-11-17 22:14:39.562500000 +0630
-++++ misc/build/silgraphite-2.3/engine/makefile.vc	2008-11-17 22:14:44.781250000 +0630
-+@@ -1,7 +1,7 @@
-+ 
-+ TARGET=graphite
-+ 
-+-!IF "$(COMEX)" == "11"
-++!IF "$(COMEX)" == "11" || "$(COMEX)" == "12"
-+ WCHAR=/Zc:wchar_t-
-+ !ELSE
-+ WCHAR=
-+--- misc/build/silgraphite-2.3/engine/makefile.vc.orig	2008-11-29 09:54:31.562500000 +0630
-++++ misc/build/silgraphite-2.3/engine/makefile.vc	2008-11-29 09:54:55.468750000 +0630
-+@@ -29,7 +29,7 @@
-+ SBREXT = .sbr
-+ 
-+ !IF "$(CFG)" == "DEBUG"
-+-CPP_DEBUG=/D "DEBUG" /Gm /GR /ZI /Od /GZ /FR"$(INTDIR)\\" /$(MLIB)d
-++CPP_DEBUG=/D "DEBUG" /Gm /GR /ZI /Od /RTC1 /FR"$(INTDIR)\\" /$(MLIB)d
-+ # CPP_DEBUG=/D "DEBUG" /Gm /GR /ZI /Od /GZ /FR"$(INTDIR)\\" /MDd
-+ 
-+ OUTDIR=.\debug
-+--- misc/build/silgraphite-2.3/wrappers/win32/WinFont.cpp.orig.cc	2008-12-02 15:36:54.968750000 +0630
-++++ misc/build/silgraphite-2.3/wrappers/win32/WinFont.cpp	2008-12-02 15:37:29.046875000 +0630
-+@@ -841,7 +841,7 @@
-+ --------------------------------------------------------------------------------------*/
-+ bool WinFont::LogFontWrapper::operator==(const WinFont::LogFontWrapper & lfw) const
-+ {
-+-	return memcmp(&m_lf, &(lfw.m_lf), sizeof(LOGFONT));
-++	return (memcmp(&m_lf, &(lfw.m_lf), sizeof(LOGFONT)) == 0);
-+ }
-+ 
-+ 
-+
-Index: graphite/makefile.mk
-===================================================================
---- graphite/makefile.mk	(.../tags/DEV300_m35)	(Revision 0)
-+++ graphite/makefile.mk	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,160 @@
-+#*************************************************************************
-+#
-+#   $RCSfile: graphite-makefile-mk.diff,v $
-+#
-+#   $Revision: 1.11 $
-+#
-+#   last change: $Author: rodo $ $Date: 2006/01/03 17:58:01 $
-+#
-+#   The Contents of this file are made available subject to the terms of
-+#   either of the following licenses
-+#
-+#          - GNU Lesser General Public License Version 2.1
-+#          - Sun Industry Standards Source License Version 1.1
-+#
-+#   Sun Microsystems Inc., October, 2000
-+#
-+#   GNU Lesser General Public License Version 2.1
-+#   =============================================
-+#   Copyright 2000 by Sun Microsystems, Inc.
-+#   901 San Antonio Road, Palo Alto, CA 94303, USA
-+#
-+#   This library is free software; you can redistribute it and/or
-+#   modify it under the terms of the GNU Lesser General Public
-+#   License version 2.1, as published by the Free Software Foundation.
-+#
-+#   This library is distributed in the hope that it will be useful,
-+#   but WITHOUT ANY WARRANTY; without even the implied warranty of
-+#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-+#   Lesser General Public License for more details.
-+#
-+#   You should have received a copy of the GNU Lesser General Public
-+#   License along with this library; if not, write to the Free Software
-+#   Foundation, Inc., 59 Temple Place, Suite 330, Boston,
-+#   MA  02111-1307  USA
-+#
-+#
-+#   Sun Industry Standards Source License Version 1.1
-+#   =================================================
-+#   The contents of this file are subject to the Sun Industry Standards
-+#   Source License Version 1.1 (the "License"); You may not use this file
-+#   except in compliance with the License. You may obtain a copy of the
-+#   License at http://www.openoffice.org/license.html.
-+#
-+#   Software provided under this License is provided on an "AS IS" basis,
-+#   WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
-+#   WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
-+#   MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
-+#   See the License for the specific provisions governing your rights and
-+#   obligations concerning the Software.
-+#
-+#   The Initial Developer of the Original Code is: Sun Microsystems, Inc.
-+#
-+#   Copyright: 2000 by Sun Microsystems, Inc.
-+#
-+#   All Rights Reserved.
-+#
-+#   Contributor(s): _______________________________________
-+#
-+#
-+#
-+#*************************************************************************
-+
-+PRJ=.
-+
-+PRJNAME=graphite
-+TARGET=so_graphite
-+
-+# --- Settings -----------------------------------------------------
-+
-+.INCLUDE :	settings.mk
-+
-+# --- Files --------------------------------------------------------
-+
-+TARFILE_NAME=silgraphite-2.3
-+PATCH_FILE_NAME=graphite-2.3.patch
-+
-+#.IF "$(OS)"=="WNT" && "$(COM)"!="GCC"
-+#CONFIGURE_DIR=win32
-+#.ELSE
-+#CONFIGURE_DIR=engine
-+#.ENDIF
-+
-+CONFIGURE_DIR=engine
-+
-+.IF "$(COM)"=="MSC"
-+# make use of stlport headerfiles
-+EXT_USE_STLPORT=TRUE
-+BUILD_ACTION=nmake
-+.IF "$(debug)"=="true"
-+BUILD_FLAGS= "CFG=DEBUG" "MLIB=MD" /F makefile.vc dll
-+.ELSE
-+BUILD_FLAGS="MLIB=MD" /F makefile.vc dll
-+.ENDIF
-+.ENDIF
-+
-+.IF "$(COM)"=="GCC"
-+
-+# Does linux want --disable-shared?
-+.IF "$(debug)"=="true"
-+CONFIGURE_FLAGS= --enable-debug --enable-static --disable-shared
-+.ELSE
-+CONFIGURE_FLAGS= --enable-final --enable-static --disable-shared
-+.ENDIF
-+EXTRA_GR_CXX_FLAGS=-fPIC
-+
-+# don't use SOLARLIB for LDFLAGS because it pulls in system graphite so build will fail
-+CONFIGURE_ACTION=bash -c 'CXXFLAGS="$(INCLUDE) $(CFLAGSCXX) $(CFLAGSCOBJ) $(CDEFS) $(CDEFSOBJ) $(SOLARINC) $(LFS_CFLAGS) $(EXTRA_GR_CXX_FLAGS)" LDFLAGS="-L$(SOLARVERSION)/$(INPATH)/lib" ./configure $(CONFIGURE_FLAGS)'
-+.ENDIF
-+
-+BUILD_DIR=$(CONFIGURE_DIR)
-+
-+.IF "$(OS)"=="WNT" && "$(COM)"!="GCC"
-+#OUT2LIB=win32$/bin.msvc$/*.lib
-+.IF "$(debug)"=="true"
-+OUT2LIB=engine$/debug$/*.lib
-+.ELSE
-+OUT2LIB=engine$/release$/*.lib
-+.ENDIF
-+.ELSE
-+OUT2LIB=engine$/src$/.libs$/libgraphite*.a
-+.ENDIF
-+
-+.IF "$(COM)"=="GCC"
-+BUILD_ACTION=$(GNUMAKE) -j$(EXTMAXPROCESS) EXT_USE_STLPORT=TRUE
-+.ENDIF
-+
-+.IF "$(OS)"=="MACOSX"
-+OUT2LIB+=src$/.libs$/libgraphite.*.dylib
-+.ELSE
-+.IF "$(OS)"=="WNT"
-+#OUT2LIB+=engine$/src$/.libs$/libgraphite*.dll
-+.IF "$(debug)"=="true"
-+OUT2BIN= \
-+    engine$/debug$/*.dll \
-+    engine$/debug$/*.pdb
-+.ELSE
-+OUT2BIN= \
-+    engine$/release$/*.dll
-+#    engine$/release$/*.pdb
-+.ENDIF
-+.ELSE
-+#OUT2LIB+=engine$/src$/.libs$/libgraphite.so.*.*.*
-+.ENDIF
-+.ENDIF
-+
-+
-+OUTDIR2INC= \
-+	engine$/include$/graphite
-+
-+.IF "$(OS)"=="WNT"
-+OUT2INC=wrappers$/win32$/WinFont.h
-+.ENDIF
-+
-+# --- Targets ------------------------------------------------------
-+
-+
-+.INCLUDE :	set_ext.mk
-+.INCLUDE :	target.mk
-+.INCLUDE :	tg_ext.mk
-+
-Index: graphite/download/silgraphite-2.3.tar.gz
-===================================================================
-Kann nicht anzeigen: Dateityp ist als binär angegeben.
-svn:mime-type = application/octet-stream
-
-Eigenschaftsänderungen: graphite/download/silgraphite-2.3.tar.gz
-___________________________________________________________________
-Hinzugefügt: svn:executable
-   + *
-Hinzugefügt: svn:mime-type
-   + application/octet-stream
-
-Index: graphite/download/Readme.txt
-===================================================================
---- graphite/download/Readme.txt	(.../tags/DEV300_m35)	(Revision 0)
-+++ graphite/download/Readme.txt	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,15 @@
-+The Graphite library is free software; you can redistribute it and/or modify
-+    it under the terms of either:
-+
-+	a) the Common Public License as published by the "Agreement
-+         Steward" for that license (currently IBM); either version 0.5
-+         of the License, or (at your option) any later version,
-+
-+    or
-+
-+	b) the GNU Lesser General Public License as published by the
-+         Free Software Foundation; either version 2.1 of License, or
-+         (at your option) any later version.
-+
-+Download source tarball of silgraphite-version.tar.gz from http://sf.net/projects/silgraphite
-+Place the downloaded tar ball in this directory.
-Index: graphite/prj/build.lst
-===================================================================
---- graphite/prj/build.lst	(.../tags/DEV300_m35)	(Revision 0)
-+++ graphite/prj/build.lst	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,3 @@
-+gr	graphite	:	stlport solenv NULL
-+gr	graphite		usr1	-	all	gr_mkout NULL
-+gr	graphite		nmake	-	all	gr_graphite NULL
-Index: graphite/prj/d.lst
-===================================================================
---- graphite/prj/d.lst	(.../tags/DEV300_m35)	(Revision 0)
-+++ graphite/prj/d.lst	(.../cws/graphite01)	(Revision 265804)
-@@ -0,0 +1,15 @@
-+mkdir: %_DEST%\inc%_EXT%\graphite
-+..\%__SRC%\inc\graphite\*.h %_DEST%\inc%_EXT%\graphite\*.h
-+..\%__SRC%\inc\WinFont.h %_DEST%\inc%_EXT%\graphite\WinFont.h
-+
-+..\%__SRC%\lib\*.so.* %_DEST%\lib%_EXT%\*.so.*
-+..\%__SRC%\lib\*.dylib %_DEST%\lib%_EXT%\*.dylib
-+..\%__SRC%\lib\*.a %_DEST%\lib%_EXT%\*.a
-+..\%__SRC%\lib\*.lib %_DEST%\lib%_EXT%\*.lib
-+..\%__SRC%\bin\*.dll %_DEST%\bin%_EXT%\*.dll
-+..\%__SRC%\bin\*.pdb %_DEST%\bin%_EXT%\*.pdb
-+..\%__SRC%\lib\graphite.lib %_DEST%\lib%_EXT%\graphite.lib
-+
-+linklib: libgraphite.so.*.*.*
-+linklib: libgraphite.dylib.*.*.*
-+#linklib: graphite.*
-
-Eigenschaftsänderungen: graphite
-___________________________________________________________________
-Hinzugefügt: svn:ignore
-   + unxlngs390x unxlngi6 unxlngmips unxirxm3 unxfbsd.pro unxols4 unxirxm3.pro unxsogi.pro unxlngp unxsoli4.pro common.pro unxlngppc64.pro unxubit8.pro wntmsci12 unxlngx6.pro unxsogi unxlngr unxols4.pro unxsols4 unxfbsdx unxhpxr unxlngs.pro unxsoli4 unxbsds.pro unxaixp.pro unxlngx6 unxlngppc4 unxfbsd unxbsds unxmacxp unxbsdi2 common unxlngr.pro unxirgm unxbsdi.pro unxbsda.pro unxirgm.pro unxsolu4.pro unxlngppc.pro unxhpgr.pro unxlngs3904 unxaixp unxsolu4 unxlngm68k unxlnga unxmacxi.pro unxirxm unxlngppc4.pro unxsols4.pro unxfbsdi unxmacxi wntmsci12.pro unxlngs390x.pro unxlngmips.pro unxhpgr unxirxm.pro unxmacxp.pro unxlngppc unxfbsdx.pro unxlnxi.pro unxlnxi unxubit8 unxhpxr.pro unxlngppc64 unxfbsdi.pro unxlngs3904.pro unxlngi6.pro unxlngp.pro unxlngs unxbsdi2.pro unxbsdi unxlnga.pro unxbsda unxsogs.pro unxsogs unxlngm68k.pro 
-
-
-Index: scp2/source/ooo/shortcut_ooo.scp
-===================================================================
---- scp2/source/ooo/shortcut_ooo.scp	(.../tags/DEV300_m35)	(Revision 265804)
-+++ scp2/source/ooo/shortcut_ooo.scp	(.../cws/graphite01)	(Revision 265804)
-@@ -116,6 +116,28 @@
- End
- 
- #endif
-+
-+Shortcut gid_Shortcut_Lib_Graphite_0
-+    FileID = gid_File_Lib_Graphite;
-+    Dir = gid_Dir_Program;
-+    Name = STRING(CONCAT2(libgraphite,UNXSUFFIX));
-+    Styles = (NETWORK,RELATIVE);
-+End
-+
-+Shortcut gid_Shortcut_Lib_Graphite_1
-+    FileID = gid_File_Lib_Graphite;
-+    Dir = gid_Dir_Program;
-+    Name = STRING(CONCAT4(libgraphite,UNXSUFFIX,.,3));
-+    Styles = (NETWORK,RELATIVE);
-+End
-+
-+Shortcut gid_Shortcut_Lib_Graphite_2
-+    FileID = gid_File_Lib_Graphite;
-+    Dir = gid_Dir_Program;
-+    Name = STRING(CONCAT4(libgraphite,UNXSUFFIX,.,3.0));
-+    Styles = (NETWORK,RELATIVE);
-+End
-+
- #endif
- 
- #ifdef MACOSX
-Index: canvas/source/directx/makefile.mk
-===================================================================
---- canvas/source/directx/makefile.mk	(.../tags/DEV300_m35)	(Revision 265804)
-+++ canvas/source/directx/makefile.mk	(.../cws/graphite01)	(Revision 265804)
-@@ -96,7 +96,7 @@
- 	$(SLO)$/dx_canvas.obj
- GDIPLUS_SLOFILES += $(SHARED_SLOFILES)
- 
--STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(VCLLIB) $(TOOLSLIB) $(UNOTOOLSLIB)
-+STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(VCLLIB) $(TOOLSLIB) $(UNOTOOLSLIB) $(I18NISOLANGLIB)
- 
- 
- ########################################################
-@@ -194,7 +194,7 @@
- SHL3TARGET=$(TARGET3).uno
- 
- # Links import libraries.
--SHL3STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(VCLLIB) $(TOOLSLIB) $(UNOTOOLSLIB)
-+SHL3STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(VCLLIB) $(TOOLSLIB) $(UNOTOOLSLIB) $(I18NISOLANGLIB)
- 
- # Specifies an import library to create. For Win32 only.
- SHL3IMPLIB=i$(TARGET3).lib
-Index: canvas/source/directx/dx_textlayout_drawhelper.cxx
-===================================================================
---- canvas/source/directx/dx_textlayout_drawhelper.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ canvas/source/directx/dx_textlayout_drawhelper.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -52,6 +52,7 @@
- #include <canvas/debug.hxx>
- #include "dx_impltools.hxx"
- #include <vcl/sysdata.hxx>
-+#include <i18npool/mslangid.hxx>
- #include "dx_textlayout_drawhelper.hxx"
- #include "dx_bitmap.hxx"
- #include "dx_canvasfont.hxx"
-@@ -135,6 +136,8 @@
-             aFont.SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
-             aFont.SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
- 
-+            aFont.SetLanguage(MsLangId::convertLocaleToLanguage(rFontRequest.Locale));
-+
-             // setup font color
-             aFont.SetColor( aColor );
-             aFont.SetFillColor( aColor );
-Index: canvas/source/vcl/makefile.mk
-===================================================================
---- canvas/source/vcl/makefile.mk	(.../tags/DEV300_m35)	(Revision 265804)
-+++ canvas/source/vcl/makefile.mk	(.../cws/graphite01)	(Revision 265804)
-@@ -73,7 +73,7 @@
- 
- SHL1TARGET=$(TARGET).uno
- 
--SHL1STDLIBS= $(TOOLSLIB) $(TKLIB) $(CPPULIB) $(SALLIB) $(VCLLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(GOODIESLIB)
-+SHL1STDLIBS= $(TOOLSLIB) $(TKLIB) $(CPPULIB) $(SALLIB) $(VCLLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(GOODIESLIB) $(I18NISOLANGLIB)
- 
- SHL1IMPLIB=i$(TARGET)
- SHL1LIBS=$(SLB)$/$(TARGET).lib
-Index: canvas/source/vcl/canvasfont.cxx
-===================================================================
---- canvas/source/vcl/canvasfont.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ canvas/source/vcl/canvasfont.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -35,7 +35,7 @@
- 
- #include <rtl/math.hxx>
- #include <basegfx/numeric/ftools.hxx>
--
-+#include <i18npool/mslangid.hxx>
- #include <vcl/metric.hxx>
- 
- #include "canvasfont.hxx"
-@@ -67,6 +67,8 @@
-         maFont->SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
-         maFont->SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
- 
-+		maFont->SetLanguage(MsLangId::convertLocaleToLanguage(rFontRequest.Locale));
-+
-         // adjust to stretched/shrinked font
-         if( !::rtl::math::approxEqual( rFontMatrix.m00, rFontMatrix.m11) )
-         {
-Index: canvas/source/cairo/cairo_canvasfont.cxx
-===================================================================
---- canvas/source/cairo/cairo_canvasfont.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ canvas/source/cairo/cairo_canvasfont.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -37,6 +37,7 @@
- #include <basegfx/numeric/ftools.hxx>
- 
- #include <vcl/metric.hxx>
-+#include <i18npool/mslangid.hxx>
- 
- #include "cairo_canvasfont.hxx"
- #include "cairo_textlayout.hxx"
-@@ -86,6 +87,8 @@
-         maFont->SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
-         maFont->SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
- 
-+        maFont->SetLanguage(MsLangId::convertLocaleToLanguage(rFontRequest.Locale));
-+
-         // adjust to stretched/shrinked font
-         if( !::rtl::math::approxEqual( rFontMatrix.m00, rFontMatrix.m11) )
-         {
-Index: canvas/source/cairo/makefile.mk
-===================================================================
---- canvas/source/cairo/makefile.mk	(.../tags/DEV300_m35)	(Revision 265804)
-+++ canvas/source/cairo/makefile.mk	(.../cws/graphite01)	(Revision 265804)
-@@ -84,7 +84,7 @@
- 
- SHL1TARGET=$(TARGET).uno
- 
--SHL1STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(VCLLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(TOOLSLIB)
-+SHL1STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(VCLLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(TOOLSLIB) $(I18NISOLANGLIB)
- 
- .IF "$(GUI)"=="UNX" 
- 
-Index: svx/source/editeng/impedit2.cxx
-===================================================================
---- svx/source/editeng/impedit2.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ svx/source/editeng/impedit2.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -1674,7 +1674,7 @@
- 		::rtl::OUString aOUText( aText );
- 		USHORT nTextLen = (USHORT)aOUText.getLength();
- 
--		long nPos = 0;
-+		sal_Int32 nPos = 0;
- 		short nScriptType = _xBI->getScriptType( aOUText, nPos );
- 		rTypes.Insert( ScriptTypePosInfo( nScriptType, (USHORT)nPos, nTextLen ), rTypes.Count() );
- 		nPos = _xBI->endOfScript( aOUText, nPos, nScriptType );
-@@ -1705,6 +1705,17 @@
-             }
-             else
-             {
-+                if ( _xBI->getScriptType( aOUText, nPos - 1 ) == i18n::ScriptType::WEAK )
-+                {
-+                    switch ( u_charType(aOUText.iterateCodePoints(&nPos, 0) ) ) {
-+                    case U_NON_SPACING_MARK:
-+                    case U_ENCLOSING_MARK:
-+                    case U_COMBINING_SPACING_MARK:
-+                        --nPos;
-+                        rTypes[rTypes.Count()-1].nEndPos--;
-+                        break;
-+                    }
-+                }
- 			    rTypes.Insert( ScriptTypePosInfo( nScriptType, (USHORT)nPos, nTextLen ), rTypes.Count() );
-             }
- 
-Index: svx/source/dialog/chardlg.hxx
-===================================================================
---- svx/source/dialog/chardlg.hxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ svx/source/dialog/chardlg.hxx	(.../cws/graphite01)	(Revision 265804)
-@@ -70,6 +70,7 @@
- 
- 	void				SetPrevFontSize( const SfxItemSet& rSet, USHORT nSlot, SvxFont& rFont );
- 	void				SetPrevFont( const SfxItemSet& rSet, USHORT nSlot, SvxFont& rFont );
-+	void				SetPrevFontLang( const SfxItemSet& rSet, USHORT nSlot, SvxFont& rFont );
- 	void				SetPrevFontStyle( const SfxItemSet& rSet, USHORT nSlotPosture, USHORT nSlotWeight, SvxFont& rFont ); // posture/weight
- 	void				SetPrevFontWidthScale( const SfxItemSet& rSet );
- 
-Index: svx/source/dialog/chardlg.cxx
-===================================================================
---- svx/source/dialog/chardlg.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ svx/source/dialog/chardlg.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -393,6 +393,11 @@
- 	SetPrevFont( rSet, SID_ATTR_CHAR_CJK_FONT, rCJKFont );
- 	SetPrevFont( rSet, SID_ATTR_CHAR_CTL_FONT, rCTLFont );
- 
-+	SetPrevFontLang( rSet, SID_ATTR_CHAR_LANGUAGE, rFont );
-+	SetPrevFontLang( rSet, SID_ATTR_CHAR_CJK_LANGUAGE, rCJKFont );
-+	SetPrevFontLang( rSet, SID_ATTR_CHAR_CTL_LANGUAGE, rCTLFont );
-+
-+
- 	// Style
- 	SetPrevFontStyle( rSet, SID_ATTR_CHAR_POSTURE, SID_ATTR_CHAR_WEIGHT, rFont );
- 	SetPrevFontStyle( rSet, SID_ATTR_CHAR_CJK_POSTURE, SID_ATTR_CHAR_CJK_WEIGHT, rCJKFont );
-@@ -494,6 +499,21 @@
- 
- // -----------------------------------------------------------------------
- 
-+void SvxCharBasePage::SetPrevFontLang( const SfxItemSet& rSet, USHORT nSlot, SvxFont& rFont )
-+{
-+	USHORT nWhich = GetWhich( nSlot );
-+	if( ISITEMSET )
-+	{
-+		const SvxLanguageItem& rItem = ( SvxLanguageItem& ) rSet.Get( nWhich );
-+		LanguageType eLangType = (LanguageType)rItem.GetValue();
-+		DBG_ASSERT( eLangType != LANGUAGE_SYSTEM, "LANGUAGE_SYSTEM not allowed" );
-+		if ( eLangType != LANGUAGE_DONTKNOW )
-+			rFont.SetLanguage( eLangType );
-+	}
-+}
-+
-+// -----------------------------------------------------------------------
-+
- void SvxCharBasePage::SetPrevFontStyle( const SfxItemSet& rSet, USHORT nPosture, USHORT nWeight, SvxFont& rFont )
- {
- 	USHORT nWhich = GetWhich( nPosture );
-@@ -777,12 +797,15 @@
-     m_pWestFontNameLB->SetModifyHdl( aLink );
-     m_pWestFontStyleLB->SetModifyHdl( aLink );
-     m_pWestFontSizeLB->SetModifyHdl( aLink );
-+    m_pWestFontLanguageLB->SetSelectHdl( aLink );
-     m_pEastFontNameLB->SetModifyHdl( aLink );
-     m_pEastFontStyleLB->SetModifyHdl( aLink );
-     m_pEastFontSizeLB->SetModifyHdl( aLink );
-+    m_pEastFontLanguageLB->SetSelectHdl( aLink );
-     m_pCTLFontNameLB->SetModifyHdl( aLink );
-     m_pCTLFontStyleLB->SetModifyHdl( aLink );
-     m_pCTLFontSizeLB->SetModifyHdl( aLink );
-+    m_pCTLFontLanguageLB->SetSelectHdl( aLink );
- 
- 	m_pImpl->m_aUpdateTimer.SetTimeoutHdl( LINK( this, SvxCharNamePage, UpdateHdl_Impl ) );
- 
-@@ -831,8 +854,10 @@
- 					const FontNameBox* _pFontNameLB,
- 					const FontStyleBox* _pFontStyleLB,
- 					const FontSizeBox* _pFontSizeLB,
-+					const SvxLanguageBox* _pFontLangLB,
- 					const FontList* _pFontList,
- 					USHORT _nFontWhich,
-+					USHORT _nFontLangWhich,
- 					USHORT _nFontHeightWhich)
- 	{
- 		Size aSize = _rFont.GetSize();
-@@ -856,6 +881,24 @@
- 				aFontInfo.SetCharSet(pFontItem->GetCharSet());
- 			}
- 		}
-+                if (_pFontLangLB->GetSavedValue() != _pFontLangLB->GetSelectEntryPos() && _pFontLangLB->GetSelectEntryPos() != LISTBOX_ENTRY_NOTFOUND)
-+		{
-+			USHORT nLangPos = _pFontLangLB->GetSelectEntryPos();
-+			LanguageType eLangType = (LanguageType)(ULONG)_pFontLangLB->GetEntryData( nLangPos );
-+			aFontInfo.SetLanguage(eLangType);
-+		}
-+		else
-+		{
-+			SfxItemState eState = _pPage->GetItemSet().GetItemState( _nFontLangWhich );
-+			if ( eState >= SFX_ITEM_DEFAULT )
-+			{
-+				const SvxLanguageItem* pLangItem = (const SvxLanguageItem*)&(_pPage->GetItemSet().Get( _nFontLangWhich ));
-+				LanguageType eLangType = (LanguageType)pLangItem->GetValue();
-+				DBG_ASSERT( eLangType != LANGUAGE_SYSTEM, "LANGUAGE_SYSTEM not allowed" );
-+				if ( eLangType != LANGUAGE_DONTKNOW )
-+					aFontInfo.SetLanguage(eLangType);
-+			}
-+		}
- 		if ( _pFontSizeLB->IsRelative() )
- 		{
- 			DBG_ASSERT( _pPage->GetItemSet().GetParent(), "No parent set" );
-@@ -886,6 +929,7 @@
- 		_rFont.SetWeight( aFontInfo.GetWeight() );
- 		_rFont.SetItalic( aFontInfo.GetItalic() );
- 		_rFont.SetSize( aFontInfo.GetSize() );
-+		_rFont.SetLanguage( aFontInfo.GetLanguage() );
- 
- 		return aFontInfo;
- 	}
-@@ -908,11 +952,11 @@
- 	// Font
- 	const FontList* pFontList = GetFontList();
- 	FontInfo aFontInfo =
--		calcFontInfo(rFont,this,m_pWestFontNameLB,m_pWestFontStyleLB,m_pWestFontSizeLB,pFontList,GetWhich( SID_ATTR_CHAR_FONT ),GetWhich( SID_ATTR_CHAR_FONTHEIGHT ));
-+		calcFontInfo(rFont,this,m_pWestFontNameLB,m_pWestFontStyleLB,m_pWestFontSizeLB,m_pWestFontLanguageLB,pFontList,GetWhich( SID_ATTR_CHAR_FONT ),GetWhich( SID_ATTR_CHAR_LANGUAGE ),GetWhich( SID_ATTR_CHAR_FONTHEIGHT ));
- 
--	calcFontInfo(rCJKFont,this,m_pEastFontNameLB,m_pEastFontStyleLB,m_pEastFontSizeLB,pFontList,GetWhich( SID_ATTR_CHAR_CJK_FONT ),GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT ));
-+	calcFontInfo(rCJKFont,this,m_pEastFontNameLB,m_pEastFontStyleLB,m_pEastFontSizeLB,m_pEastFontLanguageLB,pFontList,GetWhich( SID_ATTR_CHAR_CJK_FONT ),GetWhich( SID_ATTR_CHAR_CJK_LANGUAGE ),GetWhich( SID_ATTR_CHAR_CJK_FONTHEIGHT ));
- 
--	calcFontInfo(rCTLFont,this,m_pCTLFontNameLB,m_pCTLFontStyleLB,m_pCTLFontSizeLB,pFontList,GetWhich( SID_ATTR_CHAR_CTL_FONT ),GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT ));
-+	calcFontInfo(rCTLFont,this,m_pCTLFontNameLB,m_pCTLFontStyleLB,m_pCTLFontSizeLB,m_pCTLFontLanguageLB,pFontList,GetWhich( SID_ATTR_CHAR_CTL_FONT ),GetWhich( SID_ATTR_CHAR_CTL_LANGUAGE ),GetWhich( SID_ATTR_CHAR_CTL_FONTHEIGHT ));
- 
-     m_aPreviewWin.Invalidate();
-     m_aFontTypeFT.SetText( pFontList->GetFontMapText( aFontInfo ) );
-Index: svx/source/dialog/fntctrl.cxx
-===================================================================
---- svx/source/dialog/fntctrl.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ svx/source/dialog/fntctrl.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -36,6 +36,7 @@
- #include <sfx2/printer.hxx>		// SfxPrinter
- #include <vcl/metric.hxx>
- #include <vcl/svapp.hxx>
-+#include <unicode/uchar.h>
- #include <com/sun/star/uno/Reference.h>
- #include <com/sun/star/i18n/XBreakIterator.hpp>
- #include <com/sun/star/lang/XMultiServiceFactory.hpp>
-@@ -244,7 +245,25 @@
-         do
-         {
-             nChg = (xub_StrLen)xBreak->endOfScript( aText, nChg, nScript );
--            aScriptChg.Insert( nChg, nCnt );
-+            if (nChg < aText.Len() && nChg > 0 &&
-+                (com::sun::star::i18n::ScriptType::WEAK ==
-+                 xBreak->getScriptType(aText, nChg - 1)))
-+            {
-+                int8_t nType = u_charType(aText.GetChar(nChg) );
-+                if (nType == U_NON_SPACING_MARK || nType == U_ENCLOSING_MARK ||
-+                    nType == U_COMBINING_SPACING_MARK )
-+                {
-+                    aScriptChg.Insert( nChg - 1, nCnt );
-+                }
-+                else
-+                {
-+                    aScriptChg.Insert( nChg, nCnt );
-+                }
-+            }
-+            else
-+            {
-+                aScriptChg.Insert( nChg, nCnt );
-+            }
-             aScriptType.Insert( nScript, nCnt );
-             aTextWidth.Insert( ULONG(0), nCnt++ );
- 
-Index: svx/inc/svx/svxfont.hxx
-===================================================================
---- svx/inc/svx/svxfont.hxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ svx/inc/svx/svxfont.hxx	(.../cws/graphite01)	(Revision 265804)
-@@ -70,7 +70,8 @@
- 	inline void    SetCaseMap( const SvxCaseMap eNew ) { eCaseMap = eNew; }
- 
- 	inline LanguageType GetLanguage() const { return eLang; }
--	inline void SetLanguage( const LanguageType eNewLan ) { eLang = eNewLan; }
-+	inline void SetLanguage( const LanguageType eNewLan )
-+		{ eLang = eNewLan;  Font::SetLanguage(eNewLan); }
- 
- 	// Is-Methoden:
- 	inline BOOL IsCaseMap() const { return SVX_CASEMAP_NOT_MAPPED != eCaseMap; }
-Index: svtools/source/control/ctrltool.cxx
-===================================================================
---- svtools/source/control/ctrltool.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ svtools/source/control/ctrltool.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -161,7 +161,11 @@
- 
- static void ImplMakeSearchStringFromName( XubString& rStr )
- {
--	rStr = rStr.GetToken( 0, ';' );
-+    // check for features before alternate font separator
-+    if (rStr.Search(':') < rStr.Search(';'))
-+        rStr = rStr.GetToken( 0, ':' );
-+    else
-+        rStr = rStr.GetToken( 0, ';' );
- 	ImplMakeSearchString( rStr );
- }
- 
-Index: cppcanvas/source/mtfrenderer/implrenderer.cxx
-===================================================================
---- cppcanvas/source/mtfrenderer/implrenderer.cxx	(.../tags/DEV300_m35)	(Revision 265804)
-+++ cppcanvas/source/mtfrenderer/implrenderer.cxx	(.../cws/graphite01)	(Revision 265804)
-@@ -83,6 +83,7 @@
- #include <vcl/metric.hxx>
- #include <vcl/graphictools.hxx>
- #include <tools/poly.hxx>
-+#include <i18npool/mslangid.hxx>
- 
- #include <implrenderer.hxx>
- #include <tools.hxx>
-@@ -963,6 +964,9 @@
-                 rParms.mrParms.maFontLetterForm.getValue() :
-                 (rFont.GetItalic() == ITALIC_NONE) ? 0 : 9;
- 
-+            LanguageType aLang = rFont.GetLanguage();
-+            aFontRequest.Locale = MsLangId::convertLanguageToLocale(aLang, false);
-+
-             // setup state-local text transformation,
-             // if the font be rotated
-             const short nFontAngle( rFont.GetOrientation() );
-Index: cppcanvas/util/makefile.mk
-===================================================================
---- cppcanvas/util/makefile.mk	(.../tags/DEV300_m35)	(Revision 265804)
-+++ cppcanvas/util/makefile.mk	(.../cws/graphite01)	(Revision 265804)
-@@ -50,7 +50,7 @@
- 
- SHL1TARGET= 	$(TARGET)$(DLLPOSTFIX)
- SHL1IMPLIB= 	i$(TARGET)
--SHL1STDLIBS=	$(TOOLSLIB) $(CPPULIB) $(SALLIB) $(VCLLIB) $(COMPHELPERLIB) $(CANVASTOOLSLIB) $(BASEGFXLIB)
-+SHL1STDLIBS=	$(TOOLSLIB) $(CPPULIB) $(SALLIB) $(VCLLIB) $(COMPHELPERLIB) $(CANVASTOOLSLIB) $(BASEGFXLIB) $(I18NISOLANGLIB)
- 
- SHL1LIBS=		$(SLB)$/$(TARGET).lib
- 
diff --git a/patches/dev300/cws-graphite01-20090630.diff b/patches/dev300/cws-graphite01-20090630.diff
new file mode 100644
index 0000000..132a369
--- /dev/null
+++ b/patches/dev300/cws-graphite01-20090630.diff
@@ -0,0 +1,6952 @@
+Index: vcl/source/gdi/makefile.mk
+===================================================================
+--- vcl/source/gdi/makefile.mk	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/source/gdi/makefile.mk	(.../cws/graphite01)	(Revision 273505)
+@@ -45,6 +45,9 @@
+ .IF "$(COM)"=="ICC"
+ CDEFS+=-D_STD_NO_NAMESPACE -D_VOS_NO_NAMESPACE -D_UNO_NO_NAMESPACE
+ .ENDIF
++.IF "$(ENABLE_GRAPHITE)" == "TRUE"
++CDEFS+=-DENABLE_GRAPHITE
++.ENDIF
+ 
+ # --- Files --------------------------------------------------------
+ 
+Index: vcl/source/gdi/outdev3.cxx
+===================================================================
+--- vcl/source/gdi/outdev3.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/source/gdi/outdev3.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -67,6 +67,9 @@
+ #ifndef _OSL_FILE_H
+ #include <osl/file.h>
+ #endif
++#ifdef ENABLE_GRAPHITE
++#include <vcl/graphite_features.hxx>
++#endif
+ 
+ #include <vcl/unohelp.hxx>
+ #include <pdfwriter_impl.hxx>
+@@ -2750,6 +2753,14 @@
+     // TODO: does it pay off to improve this hash function?
+     static FontNameHash aFontNameHash;
+     size_t nHash = aFontNameHash( rFSD.maSearchName );
++#ifdef ENABLE_GRAPHITE
++    // check for features and generate a unique hash if necessary
++    if (rFSD.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
++        != STRING_NOTFOUND)
++    {
++        nHash = aFontNameHash( rFSD.maTargetName );
++    }
++#endif
+     nHash += 11 * rFSD.mnHeight;
+     nHash += 19 * rFSD.meWeight;
+     nHash += 29 * rFSD.meItalic;
+@@ -2801,6 +2812,15 @@
+             return false;
+     }
+ 
++#ifdef ENABLE_GRAPHITE
++    // check for features
++    if ((rA.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
++         != STRING_NOTFOUND ||
++         rB.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
++         != STRING_NOTFOUND) && rA.maTargetName != rB.maTargetName)
++        return false;
++#endif
++
+     return true;
+ }
+ 
+@@ -2838,7 +2858,12 @@
+         // if it is already known get its normalized search name
+         FontNameList::const_iterator it_name = maFontNameList.find( aSearchName );
+         if( it_name != maFontNameList.end() )
+-            if( !(*it_name).second.EqualsAscii( "hg", 0, 2) )
++            if( !(*it_name).second.EqualsAscii( "hg", 0, 2)
++#ifdef ENABLE_GRAPHITE
++                && (aSearchName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
++                    == STRING_NOTFOUND)
++#endif
++            )
+                 aSearchName = (*it_name).second;
+     }
+ 
+@@ -2943,6 +2968,22 @@
+     {
+         rFSD.maTargetName = GetNextFontToken( rFSD.maName, nTokenPos );
+         aSearchName = rFSD.maTargetName;
++
++#ifdef ENABLE_GRAPHITE
++        // Until features are properly supported, they are appended to the
++        // font name, so we need to strip them off so the font is found.
++        xub_StrLen nFeat = aSearchName.Search(grutils::GrFeatureParser::FEAT_PREFIX);
++        String aOrigName = rFSD.maTargetName;
++        String aBaseFontName(aSearchName, 0, (nFeat != STRING_NOTFOUND)?nFeat:aSearchName.Len());
++        if (nFeat != STRING_NOTFOUND && STRING_NOTFOUND !=
++            aSearchName.Search(grutils::GrFeatureParser::FEAT_ID_VALUE_SEPARATOR, nFeat))
++        {
++            aSearchName = aBaseFontName;
++            rFSD.maTargetName = aBaseFontName;
++        }
++
++#endif
++
+         ImplGetEnglishSearchFontName( aSearchName );
+         ImplFontSubstitute( aSearchName, nSubstFlags, pDevSpecific );
+         // #114999# special emboldening for Ricoh fonts
+@@ -2973,6 +3014,10 @@
+             }
+         }
+ 
++#ifdef ENABLE_GRAPHITE
++		// restore the features to make the font selection data unique
++		rFSD.maTargetName = aOrigName;
++#endif
+         // check if the current font name token or its substitute is valid
+         ImplDevFontListData* pFoundData = ImplFindBySearchName( aSearchName );
+         if( pFoundData )
+@@ -2981,16 +3026,21 @@
+         // some systems provide special customization
+         // e.g. they suggest "serif" as UI-font, but this name cannot be used directly
+         //      because the system wants to map it to another font first, e.g. "Helvetica"
++#ifdef ENABLE_GRAPHITE
++		// use the target name to search in the prematch hook
++		rFSD.maTargetName = aBaseFontName;
++#endif
+         if( mpPreMatchHook )
+-        {
+             if( mpPreMatchHook->FindFontSubstitute( rFSD ) )
+-            {
+                 ImplGetEnglishSearchFontName( aSearchName );
+-                pFoundData = ImplFindBySearchName( aSearchName );
+-                if( pFoundData )
+-                    return pFoundData;
+-            }
+-        }
++#ifdef ENABLE_GRAPHITE
++	    // the prematch hook uses the target name to search, but we now need
++	    // to restore the features to make the font selection data unique
++	    rFSD.maTargetName = aOrigName;
++#endif
++		pFoundData = ImplFindBySearchName( aSearchName );
++		if( pFoundData )
++			return pFoundData;
+ 
+         // break after last font name token was checked unsuccessfully
+         if( nTokenPos == STRING_NOTFOUND)
+@@ -5441,6 +5491,7 @@
+     DBG_CHKOBJ( &rNewFont, Font, NULL );
+ 
+     Font aFont( rNewFont );
++    aFont.SetLanguage(rNewFont.GetLanguage());
+     if ( mnDrawMode & (DRAWMODE_BLACKTEXT | DRAWMODE_WHITETEXT | DRAWMODE_GRAYTEXT | DRAWMODE_GHOSTEDTEXT | DRAWMODE_SETTINGSTEXT |
+                        DRAWMODE_BLACKFILL | DRAWMODE_WHITEFILL | DRAWMODE_GRAYFILL | DRAWMODE_NOFILL |
+                        DRAWMODE_GHOSTEDFILL | DRAWMODE_SETTINGSFILL ) )
+Index: vcl/source/gdi/sallayout.cxx
+===================================================================
+--- vcl/source/gdi/sallayout.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/source/gdi/sallayout.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -63,6 +63,26 @@
+ 
+ #include <algorithm>
+ 
++#ifdef DEBUG
++//#define MULTI_SL_DEBUG
++#endif
++
++#ifdef MULTI_SL_DEBUG
++#include <string>
++FILE * mslLogFile = NULL;
++FILE * mslLog()
++{
++#ifdef MSC
++	std::string logFileName(getenv("TEMP"));
++	logFileName.append("\\msllayout.log");
++    if (mslLogFile == NULL) mslLogFile = fopen(logFileName.c_str(),"w");
++    else fflush(mslLogFile);
++    return mslLogFile;
++#else
++    return stdout;
++#endif
++}
++#endif
+ // =======================================================================
+ 
+ // TODO: ask the glyph directly, for now we need this method because of #i99367#
+@@ -1157,11 +1177,17 @@
+     for( int nCharPos = i = -1; rArgs.GetNextPos( &nCharPos, &bRTL ); )
+     {
+         n = nCharPos - rArgs.mnMinCharPos;
+-        i = pLogCluster[ n ];
+-        long nDelta = rArgs.mpDXArray[ n ] ;
+-        if( n > 0 )
+-            nDelta -= rArgs.mpDXArray[ n-1 ];
+-        pNewGlyphWidths[ i ] += nDelta * mnUnitsPerPixel;
++        if( (n < 0) || (nCharCount <= n) )  continue;
++
++        if( pLogCluster[ n ] >= 0 )
++            i = pLogCluster[ n ];
++        if( i >= 0 )
++        {
++            long nDelta = rArgs.mpDXArray[ n ] ;
++            if( n > 0 )
++                nDelta -= rArgs.mpDXArray[ n-1 ];
++            pNewGlyphWidths[ i ] += nDelta * mnUnitsPerPixel;
++        }
+     }
+ 
+     // move cluster positions using the adjusted widths
+@@ -1768,6 +1794,19 @@
+         }
+     }
+ 
++    // Compute rtl flags, since in some scripts glyphs/char order can be
++    // reversed for a few character sequencies e.g. Myanmar
++    std::vector<bool> vRtl(rArgs.mnEndCharPos - rArgs.mnMinCharPos, false);
++    rArgs.ResetPos();
++    bool bRtl;
++    int nRunStart, nRunEnd;
++    while (rArgs.GetNextRun(&nRunStart, &nRunEnd, &bRtl))
++    {
++        if (bRtl) std::fill(vRtl.begin() + nRunStart - rArgs.mnMinCharPos,
++                            vRtl.begin() + nRunEnd - rArgs.mnMinCharPos, true);
++    }
++    rArgs.ResetPos();
++
+     // prepare "merge sort"
+     int nStartOld[ MAX_FALLBACK ];
+     int nStartNew[ MAX_FALLBACK ];
+@@ -1804,6 +1843,10 @@
+         nStartNew[ nLevel ] = nStartOld[ nLevel ] = 0;
+         nValid[ nLevel ] = mpLayouts[n]->GetNextGlyphs( 1, &nDummy, aPos,
+             nStartNew[ nLevel ], &nGlyphAdv[ nLevel ], &nCharPos[ nLevel ] );
++#ifdef MULTI_SL_DEBUG
++        if (nValid[nLevel]) fprintf(mslLog(), "layout[%d]->GetNextGlyphs %d,%d x%d a%d c%d %x\n", n, nStartOld[nLevel], nStartNew[nLevel], aPos.X(), nGlyphAdv[nLevel], nCharPos[nLevel],
++            rArgs.mpStr[nCharPos[nLevel]]);
++#endif
+         if( (n > 0) && !nValid[ nLevel ] )
+         {
+             // an empty fallback layout can be released
+@@ -1829,6 +1872,9 @@
+     for( n = 0; n < nLevel; ++n )
+         maFallbackRuns[n].ResetPos();
+     int nActiveCharPos = nCharPos[0];
++    int nLastRunEndChar = (vRtl[nActiveCharPos - mnMinCharPos])?
++        rArgs.mnEndCharPos : rArgs.mnMinCharPos - 1;
++    int nRunVisibleEndChar = nCharPos[0];
+     while( nValid[0] && (nLevel > 0))
+     {
+         // find best fallback level
+@@ -1864,6 +1910,9 @@
+                 nStartOld[0] = nStartNew[0];
+                 nValid[0] = mpLayouts[0]->GetNextGlyphs( 1, &nDummy, aPos,
+                     nStartNew[0], &nGlyphAdv[0], &nCharPos[0] );
++#ifdef MULTI_SL_DEBUG
++                if (nValid[0]) fprintf(mslLog(), "layout[0]->GetNextGlyphs %d,%d x%d a%d c%d %x\n", nStartOld[0], nStartNew[0], aPos.X(), nGlyphAdv[0], nCharPos[0], rArgs.mpStr[nCharPos[0]]);
++#endif
+                 if( !nValid[0] )
+                    break;
+             }
+@@ -1881,7 +1930,9 @@
+             int nOrigCharPos = nCharPos[n];
+             nValid[n] = mpLayouts[n]->GetNextGlyphs( 1, &nDummy, aPos,
+                 nStartNew[n], &nGlyphAdv[n], &nCharPos[n] );
+-
++#ifdef MULTI_SL_DEBUG
++            if (nValid[n]) fprintf(mslLog(), "layout[%d]->GetNextGlyphs %d,%d a%d c%d %x\n", n, nStartOld[n], nStartNew[n], nGlyphAdv[n], nCharPos[n], rArgs.mpStr[nCharPos[n]]);
++#endif
+             // break after last glyph of active layout
+             if( !nValid[n] )
+             {
+@@ -1927,6 +1978,27 @@
+                     { maFallbackRuns[0].NextRun(); break; }
+                 bKeepNotDef = bNeedFallback;
+             }
++            // check for reordered glyphs
++            if (aMultiArgs.mpDXArray &&
++                nRunVisibleEndChar < mnEndCharPos &&
++                nRunVisibleEndChar >= mnMinCharPos &&
++                nCharPos[n] < mnEndCharPos &&
++                nCharPos[n] >= mnMinCharPos)
++            {
++                if (vRtl[nActiveCharPos - mnMinCharPos])
++                {
++                    if (aMultiArgs.mpDXArray[nRunVisibleEndChar-mnMinCharPos]
++                        >= aMultiArgs.mpDXArray[nCharPos[n] - mnMinCharPos])
++                    {
++                        nRunVisibleEndChar = nCharPos[n];
++                    }
++                }
++                else if (aMultiArgs.mpDXArray[nRunVisibleEndChar-mnMinCharPos]
++                         <= aMultiArgs.mpDXArray[nCharPos[n] - mnMinCharPos])
++                {
++                    nRunVisibleEndChar = nCharPos[n];
++                }
++            }
+         }
+ 
+         // if a justification array is available
+@@ -1936,16 +2008,40 @@
+             // the run advance is the width from the first char
+             // in the run to the first char in the next run
+             nRunAdvance = 0;
+-            const bool bLTR = (nActiveCharPos < nCharPos[0]);
++#ifdef MULTI_SL_DEBUG
++            const bool bLTR = !(vRtl[nActiveCharPos - mnMinCharPos]);//(nActiveCharPos < nCharPos[0]);
++            int nOldRunAdv = 0;
+             int nDXIndex = nCharPos[0] - mnMinCharPos - bLTR;
+             if( nDXIndex >= 0 )
+-                nRunAdvance += aMultiArgs.mpDXArray[ nDXIndex ];
++                nOldRunAdv += aMultiArgs.mpDXArray[ nDXIndex ];
+             nDXIndex = nActiveCharPos - mnMinCharPos - bLTR;
+             if( nDXIndex >= 0 )
+-                nRunAdvance -= aMultiArgs.mpDXArray[ nDXIndex ];
++                nOldRunAdv -= aMultiArgs.mpDXArray[ nDXIndex ];
+             if( !bLTR )
+-                nRunAdvance = -nRunAdvance;
+-
++                nOldRunAdv = -nOldRunAdv;
++#endif
++            if (vRtl[nActiveCharPos - mnMinCharPos])
++            {
++              if (nRunVisibleEndChar > mnMinCharPos && nRunVisibleEndChar <= mnEndCharPos)
++                  nRunAdvance -= aMultiArgs.mpDXArray[nRunVisibleEndChar - 1 - mnMinCharPos];
++              if (nLastRunEndChar > mnMinCharPos && nLastRunEndChar <= mnEndCharPos)
++                  nRunAdvance += aMultiArgs.mpDXArray[nLastRunEndChar - 1 - mnMinCharPos];
++#ifdef MULTI_SL_DEBUG
++              fprintf(mslLog(), "rtl visible %d-%d,%d-%d adv%d(%d)\n", nLastRunEndChar-1, nRunVisibleEndChar-1, nActiveCharPos - bLTR, nCharPos[0] - bLTR, nRunAdvance, nOldRunAdv);
++#endif
++            }
++            else
++            {
++                if (nRunVisibleEndChar >= mnMinCharPos)
++                  nRunAdvance += aMultiArgs.mpDXArray[nRunVisibleEndChar - mnMinCharPos];
++                if (nLastRunEndChar >= mnMinCharPos)
++                  nRunAdvance -= aMultiArgs.mpDXArray[nLastRunEndChar - mnMinCharPos];
++#ifdef MULTI_SL_DEBUG
++                fprintf(mslLog(), "visible %d-%d,%d-%d adv%d(%d)\n", nLastRunEndChar, nRunVisibleEndChar, nActiveCharPos - bLTR, nCharPos[0] - bLTR, nRunAdvance, nOldRunAdv);
++#endif
++            }
++            nLastRunEndChar = nRunVisibleEndChar;
++            nRunVisibleEndChar = nCharPos[0];
+             // the requested width is still in pixel units
+             // => convert it to base level font units
+             nRunAdvance *= mnUnitsPerPixel;
+@@ -1963,9 +2059,27 @@
+ 
+         // prepare for next fallback run
+         nActiveCharPos = nCharPos[0];
++        // it essential that the runs don't get ahead of themselves and in the
++        // if( bKeepNotDef && !bNeedFallback ) statement above, the next run may
++        // have already been reached on the base level
+         for( int i = nFBLevel; --i >= 0;)
+-            if( !maFallbackRuns[i].PosIsInRun( nActiveCharPos ) )
+-                maFallbackRuns[i].NextRun();
++        {
++            if (maFallbackRuns[i].GetRun(&nRunStart, &nRunEnd, &bRtl))
++            {
++                if (bRtl)
++                {
++                    if (nRunStart > nActiveCharPos)
++                        maFallbackRuns[i].NextRun();
++                }
++                else
++                {
++                    if (nRunEnd <= nActiveCharPos)
++                        maFallbackRuns[i].NextRun();
++                }
++            }
++        }
++//            if( !maFallbackRuns[i].PosIsInRun( nActiveCharPos ) )
++//                maFallbackRuns[i].NextRun();
+     }
+ 
+     mpLayouts[0]->Simplify( true );
+Index: vcl/source/glyphs/graphite_textsrc.cxx
+===================================================================
+--- vcl/source/glyphs/graphite_textsrc.cxx	(.../tags/DEV300_m49)	(Revision 0)
++++ vcl/source/glyphs/graphite_textsrc.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,155 @@
++//
++// C++ Implementation: Graphite to SAL adaptor classes
++//
++// Description: Implements the Graphite interfaces IGrTextSource and
++//              IGrGraphics which provide Graphite with access to the
++//              app's text storage system and the platform's font and
++//              graphics systems.
++//
++// Author: Tim Eves <tim_eves at sil.org>
++//
++// Copyright: Copyright (C) 2003-2004 SIL International.
++//            All rights reserved. Distributable under the terms of either
++//            the Common Public License or the GNU Lesser General Public
++//            License.
++//
++
++// We need this to enable namespace support in libgrengine headers.
++#define GR_NAMESPACE
++
++// Header files
++//
++// Standard Library
++#include <string>
++#include <cassert>
++#include "graphite_textsrc.hxx"
++#include <vcl/graphite_features.hxx>
++
++// class TextSourceAdaptor implementation.
++//
++TextSourceAdaptor::~TextSourceAdaptor()
++{
++    delete mpFeatures;
++}
++
++gr::UtfType TextSourceAdaptor::utfEncodingForm() {
++    return gr::kutf16;
++}
++
++
++size_t TextSourceAdaptor::getLength()
++{
++    return maLayoutArgs.mnLength;
++}
++
++
++size_t  TextSourceAdaptor::fetch(gr::toffset, size_t, gr::utf32 *)
++{
++    assert(false);
++    return 0;
++}
++
++
++size_t  TextSourceAdaptor::fetch(gr::toffset offset, size_t char_count, gr::utf16 * char_buffer)
++{
++  assert(char_buf);
++
++  size_t copy_count =  std::min(size_t(maLayoutArgs.mnLength), char_count);
++  std::copy(maLayoutArgs.mpStr + offset, maLayoutArgs.mpStr + offset + copy_count, char_buffer);
++
++  return copy_count;
++}
++
++
++size_t TextSourceAdaptor::fetch(gr::toffset, size_t, gr::utf8  *)
++{
++    assert(false);
++    return 0;
++}
++
++
++inline void TextSourceAdaptor::getCharProperties(const int nCharIdx, int & min, int & lim, size_t & depth)
++{
++    maLayoutArgs.ResetPos();
++    bool rtl = maLayoutArgs.mnFlags & SAL_LAYOUT_BIDI_RTL;
++    for(depth = ((rtl)? 1:0); maLayoutArgs.maRuns.GetRun(&min, &lim, &rtl); maLayoutArgs.maRuns.NextRun())
++    {
++        if (min > nCharIdx)
++            break;
++        // Only increase the depth when a change of direction occurs.
++        depth += int(rtl ^ bool(depth & 0x1));
++        if (min <= nCharIdx && nCharIdx < lim)
++            break;
++    }
++    // If there is no run for this position increment the depth, but don't
++    // change if this is out of bounds context
++    if (lim > 0 && nCharIdx >= lim && nCharIdx < maLayoutArgs.mnEndCharPos)
++        depth++;
++}
++
++
++bool TextSourceAdaptor::getRightToLeft(gr::toffset nCharIdx)
++{
++    size_t depth;
++    int min, lim = 0;
++    getCharProperties(nCharIdx, min, lim, depth);
++    //printf("getRtl %d,%x=%d\n", nCharIdx, maLayoutArgs.mpStr[nCharIdx], depth & 0x1);
++    return depth & 0x1;
++}
++
++
++unsigned int TextSourceAdaptor::getDirectionDepth(gr::toffset nCharIdx)
++{
++    size_t depth;
++    int min, lim;
++    getCharProperties(nCharIdx, min, lim, depth);
++    //printf("getDirectionDepth %d,%x=%d\n", nCharIdx, maLayoutArgs.mpStr[nCharIdx], depth);
++    return depth;
++}
++
++
++float TextSourceAdaptor::getVerticalOffset(gr::toffset)
++{
++    return 0.0f;    //TODO: Implement correctly
++}
++
++gr::isocode TextSourceAdaptor::getLanguage(gr::toffset)
++{
++    if (mpFeatures && mpFeatures->hasLanguage())
++        return mpFeatures->getLanguage();
++    gr::isocode unknown = {{0,0,0,0}};
++    return unknown;
++}
++
++std::pair<gr::toffset, gr::toffset> TextSourceAdaptor::propertyRange(gr::toffset nCharIdx)
++{
++
++    if (nCharIdx < unsigned(maLayoutArgs.mnMinCharPos))
++        return std::make_pair(0, maLayoutArgs.mnMinCharPos);
++
++    if (nCharIdx < mnEnd)
++        return std::make_pair(maLayoutArgs.mnMinCharPos, mnEnd);
++
++    return std::make_pair(mnEnd, maLayoutArgs.mnLength);
++}
++
++size_t TextSourceAdaptor::getFontFeatures(gr::toffset, gr::FeatureSetting * settings)
++{
++    if (mpFeatures) return mpFeatures->getFontFeatures(settings);
++    return 0;
++}
++
++
++bool TextSourceAdaptor::sameSegment(gr::toffset char_idx1, gr::toffset char_idx2)
++{
++    const std::pair<gr::toffset, gr::toffset>
++    range1 = propertyRange(char_idx1),
++    range2 = propertyRange(char_idx2);
++
++    return range1 == range2;
++}
++
++void TextSourceAdaptor::setFeatures(const grutils::GrFeatureParser * pFeatures)
++{
++    mpFeatures = new grutils::GrFeatureParser(*pFeatures);
++}
+Index: vcl/source/glyphs/graphite_adaptors.cxx
+===================================================================
+--- vcl/source/glyphs/graphite_adaptors.cxx	(.../tags/DEV300_m49)	(Revision 0)
++++ vcl/source/glyphs/graphite_adaptors.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,307 @@
++//
++// C++ Implementation: Graphite to SAL adaptor classes
++//
++// Description: Implements the Graphite interfaces IGrTextSource and
++//              IGrGraphics which provide Graphite with access to the
++//              app's text storage system and the platform's font and
++//              graphics systems.
++//
++// Author: Tim Eves <tim_eves at sil.org>
++//
++// Copyright: Copyright (C) 2003-2004 SIL International.
++//            All rights reserved. Distributable under the terms of either
++//            the Common Public License or the GNU Lesser General Public
++//            License.
++//
++
++// We need this to enable namespace support in libgrengine headers.
++#define GR_NAMESPACE
++
++// Header files
++//
++// Standard Library
++#include <string>
++#include <cassert>
++// Libraries
++#include <rtl/string.hxx>
++#include <rtl/ustring.hxx>
++#include <i18npool/mslangid.hxx>
++// Platform
++#ifndef MSC
++#include <saldisp.hxx>
++
++#include <vcl/salgdi.hxx>
++
++#include <freetype/ftsynth.h>
++
++// Module
++#include "gcach_ftyp.hxx"
++
++#include <vcl/graphite_features.hxx>
++#include <vcl/graphite_adaptors.hxx>
++
++// Module private type definitions and forward declarations.
++//
++using gr::GrResult;
++namespace
++{
++    inline float from_hinted(const int x) {
++        return static_cast<float>(x + 32) / 64.0;
++    }
++    typedef std::hash_map<long,bool> SilfMap;
++    SilfMap sSilfMap;
++}
++
++// class CharacterRenderProperties implentation.
++//
++FontProperties::FontProperties(const FreetypeServerFont &font) throw()
++{
++    clrFore = gr::kclrBlack;
++    clrBack = gr::kclrTransparent;
++
++    pixHeight = from_hinted(font.GetMetricsFT().height);
++
++    switch (font.GetFontSelData().meWeight)
++    {
++        case WEIGHT_SEMIBOLD: case WEIGHT_BOLD:
++        case WEIGHT_ULTRABOLD: case WEIGHT_BLACK:
++            fBold = true;
++            break;
++        default :
++            fBold = false;
++    }
++
++    switch (font.GetFontSelData().meItalic)
++    {
++        case ITALIC_NORMAL: case ITALIC_OBLIQUE:
++            fItalic = true;
++            break;
++        default :
++            fItalic = false;
++    }
++
++    // Get the font name.
++    const sal_Unicode    * name = font.GetFontSelData().maName.GetBuffer();
++    const size_t          name_sz = std::min(sizeof szFaceName/sizeof(wchar_t)-1,
++                    size_t(font.GetFontSelData().maName.Len()));
++
++    std::copy(name, name + name_sz, szFaceName);
++    szFaceName[name_sz] = '\0';
++}
++
++// class GraphiteFontAdaptor implementaion.
++//
++GraphiteFontAdaptor::GraphiteFontAdaptor(ServerFont & sfont, const sal_Int32 dpiX, const sal_Int32 dpiY)
++  :    mrFont(static_cast<FreetypeServerFont &>(sfont)),
++    maFontProperties(static_cast<FreetypeServerFont &>(sfont)),
++    mnDpiX(dpiX),
++    mnDpiY(dpiY),
++    mfAscent(from_hinted(static_cast<FreetypeServerFont &>(sfont).GetMetricsFT().ascender)),
++    mfDescent(from_hinted(static_cast<FreetypeServerFont &>(sfont).GetMetricsFT().descender)),
++    mfEmUnits(static_cast<FreetypeServerFont &>(sfont).GetMetricsFT().y_ppem),
++    mpFeatures(NULL)
++{
++    //std::wstring face_name(maFontProperties.szFaceName);
++    const rtl::OString aLang = MsLangId::convertLanguageToIsoByteString( sfont.GetFontSelData().meLanguage );
++#ifdef DEBUG
++    printf("GraphiteFontAdaptor %lx\n", (long)this);
++#endif
++    rtl::OString name = rtl::OUStringToOString(
++        sfont.GetFontSelData().maTargetName, RTL_TEXTENCODING_UTF8 );
++    sal_Int32 nFeat = name.indexOf(grutils::GrFeatureParser::FEAT_PREFIX) + 1;
++    if (nFeat > 0)
++    {
++        rtl::OString aFeat = name.copy(nFeat, name.getLength() - nFeat);
++        mpFeatures = new grutils::GrFeatureParser(*this, aFeat.getStr(), aLang.getStr());
++#ifdef DEBUG
++        printf("GraphiteFontAdaptor %s/%s/%s %x language %d features %d errors\n",
++            rtl::OUStringToOString( sfont.GetFontSelData().maName,
++            RTL_TEXTENCODING_UTF8 ).getStr(),
++            rtl::OUStringToOString( sfont.GetFontSelData().maTargetName,
++            RTL_TEXTENCODING_UTF8 ).getStr(),
++            rtl::OUStringToOString( sfont.GetFontSelData().maSearchName,
++            RTL_TEXTENCODING_UTF8 ).getStr(),
++            sfont.GetFontSelData().meLanguage,
++            (int)mpFeatures->getFontFeatures(NULL), mpFeatures->parseErrors());
++#endif
++    }
++    else
++    {
++        mpFeatures = new grutils::GrFeatureParser(*this, aLang.getStr());
++    }
++}
++
++GraphiteFontAdaptor::GraphiteFontAdaptor(const GraphiteFontAdaptor &rhs) throw()
++ :    Font(rhs),
++     mrFont (rhs.mrFont), maFontProperties(rhs.maFontProperties),
++    mnDpiX(rhs.mnDpiX), mnDpiY(rhs.mnDpiY),
++    mfAscent(rhs.mfAscent), mfDescent(rhs.mfDescent), mfEmUnits(rhs.mfEmUnits),
++    mpFeatures(NULL)
++{
++    if (rhs.mpFeatures) mpFeatures = new grutils::GrFeatureParser(*(rhs.mpFeatures));
++}
++
++
++GraphiteFontAdaptor::~GraphiteFontAdaptor() throw()
++{
++    maGlyphMetricMap.clear();
++    if (mpFeatures) delete mpFeatures;
++    mpFeatures = NULL;
++}
++
++void GraphiteFontAdaptor::UniqueCacheInfo(std::wstring & face_name_out, bool & bold_out, bool & italic_out)
++{
++    face_name_out = maFontProperties.szFaceName;
++    bold_out = maFontProperties.fBold;
++    italic_out = maFontProperties.fItalic;
++}
++
++bool GraphiteFontAdaptor::IsGraphiteEnabledFont(ServerFont & font) throw()
++{
++    // NOTE: this assumes that the same FTFace pointer won't be reused,
++    // so FtFontInfo::ReleaseFaceFT must only be called at shutdown.
++    FreetypeServerFont & aFtFont = dynamic_cast<FreetypeServerFont &>(font);
++    FT_Face aFace = reinterpret_cast<FT_FaceRec_*>(aFtFont.GetFtFace());
++    SilfMap::iterator i = sSilfMap.find(reinterpret_cast<long>(aFace));
++    if (i != sSilfMap.end())
++    {
++#ifdef DEBUG
++        if (static_cast<bool>(aFtFont.GetTable("Silf", 0)) != (*i).second)
++            printf("Silf cache font mismatch\n");
++#endif
++        return (*i).second;
++    }
++    bool bHasSilf = aFtFont.GetTable("Silf", 0);
++    sSilfMap[reinterpret_cast<long>(aFace)] = bHasSilf;
++    return bHasSilf;
++}
++
++
++gr::Font * GraphiteFontAdaptor::copyThis() {
++    return new GraphiteFontAdaptor(*this);
++}
++
++
++unsigned int GraphiteFontAdaptor::getDPIx() {
++    return mnDpiX;
++}
++
++
++unsigned int GraphiteFontAdaptor::getDPIy() {
++    return mnDpiY;
++}
++
++
++float GraphiteFontAdaptor::ascent() {
++    return mfAscent;
++}
++
++
++float GraphiteFontAdaptor::descent() {
++    return mfDescent;
++}
++
++
++bool GraphiteFontAdaptor::bold() {
++    return maFontProperties.fBold;
++}
++
++
++bool GraphiteFontAdaptor::italic() {
++    return maFontProperties.fItalic;
++}
++
++
++float GraphiteFontAdaptor::height() {
++    return maFontProperties.pixHeight;
++}
++
++
++void GraphiteFontAdaptor::getFontMetrics(float * ascent_out, float * descent_out, float * em_square_out) {
++    if (ascent_out)        *ascent_out    = mfAscent;
++    if (descent_out)    *descent_out   = mfDescent;
++    if (em_square_out)    *em_square_out = mfEmUnits;
++}
++
++
++const void * GraphiteFontAdaptor::getTable(gr::fontTableId32 table_id, size_t * buffer_sz)
++{
++    char tag_name[5] = {char(table_id >> 24), char(table_id >> 16), char(table_id >> 8), char(table_id), 0};
++    ULONG temp = *buffer_sz;
++
++    const void * const tbl_buf = static_cast<FreetypeServerFont &>(mrFont).GetTable(tag_name, &temp);
++    *buffer_sz = temp;
++
++    return tbl_buf;
++}
++
++#define fix26_6(x) (x >> 6) + (x & 32 ? (x > 0 ? 1 : 0) : (x < 0 ? -1 : 0))
++
++// Return the glyph's metrics in pixels.
++void GraphiteFontAdaptor::getGlyphMetrics(gr::gid16 nGlyphId, gr::Rect & aBounding, gr::Point & advances)
++{
++    // Graphite gets really confused if the glyphs have been transformed, so
++    // if orientation has been set we can't use the font's glyph cache
++    // unfortunately the font selection data, doesn't always have the orientation
++    // set, even if it was when the glyphs were cached, so we use our own cache.
++
++//         const GlyphMetric & metric = mrFont.GetGlyphMetric(nGlyphId);
++//
++//         aBounding.right  = aBounding.left = metric.GetOffset().X();
++//         aBounding.bottom = aBounding.top  = -metric.GetOffset().Y();
++//         aBounding.right  += metric.GetSize().Width();
++//         aBounding.bottom -= metric.GetSize().Height();
++//
++//         advances.x = metric.GetDelta().X();
++//         advances.y = -metric.GetDelta().Y();
++
++    GlyphMetricMap::const_iterator gm_itr = maGlyphMetricMap.find(nGlyphId);
++    if (gm_itr != maGlyphMetricMap.end())
++    {
++        // We've cached the results from last time.
++        aBounding = gm_itr->second.first;
++        advances    = gm_itr->second.second;
++    }
++    else
++    {
++        // We need to look up the glyph.
++        FT_Int nLoadFlags = mrFont.GetLoadFlags();
++
++        FT_Face aFace = reinterpret_cast<FT_Face>(mrFont.GetFtFace());
++        if (!aFace)
++        {
++            aBounding.top = aBounding.bottom = aBounding.left = aBounding.right = 0;
++            advances.x = advances.y = 0;
++            return;
++        }
++        FT_Error aStatus = -1;
++        aStatus = FT_Load_Glyph(aFace, nGlyphId, nLoadFlags);
++        if( aStatus != FT_Err_Ok || (!aFace->glyph))
++        {
++            aBounding.top = aBounding.bottom = aBounding.left = aBounding.right = 0;
++            advances.x = advances.y = 0;
++            return;
++        }
++        // check whether we need synthetic bold/italic otherwise metric is wrong
++        if (mrFont.NeedsArtificialBold())
++            FT_GlyphSlot_Embolden(aFace->glyph);
++
++        if (mrFont.NeedsArtificialItalic())
++            FT_GlyphSlot_Oblique(aFace->glyph);
++
++        const FT_Glyph_Metrics &gm = aFace->glyph->metrics;
++
++        // Fill out the bounding box an advances.
++        aBounding.top = aBounding.bottom = fix26_6(gm.horiBearingY);
++        aBounding.bottom -= fix26_6(gm.height);
++        aBounding.left = aBounding.right = fix26_6(gm.horiBearingX);
++        aBounding.right += fix26_6(gm.width);
++        advances.x = fix26_6(gm.horiAdvance);
++        advances.y = 0;
++
++        // Now add an entry to our metrics map.
++        maGlyphMetricMap[nGlyphId] = std::make_pair(aBounding, advances);
++    }
++}
++
++#endif
+Index: vcl/source/glyphs/graphite_layout.cxx
+===================================================================
+--- vcl/source/glyphs/graphite_layout.cxx	(.../tags/DEV300_m49)	(Revision 0)
++++ vcl/source/glyphs/graphite_layout.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,1346 @@
++//
++// C++ Implementation: GraphiteLayout
++//
++// Description: An implementation of the SalLayout interface that uses the
++//              Graphite engine.
++//
++// Author: Tim Eves <tim_eves at sil.org>
++//         Keith Stribley <devel at thanlwinsoft.org>
++//
++// Copyright: Copyright (C) 2003,2008 SIL International.
++//            All rights reserved. Distributable under the terms of either
++//            the Common Public License or the GNU Lesser General Public
++//            License.
++//
++
++// We need this to enable namespace support in libgrengine headers.
++#define GR_NAMESPACE
++
++// Enable lots of debug info
++#ifdef DEBUG
++//#define GRLAYOUT_DEBUG 1
++//#undef NDEBUG
++#endif
++
++// Header files
++//
++// Standard Library
++#include <algorithm>
++#include <cassert>
++#include <functional>
++#include <limits>
++#include <numeric>
++#include <deque>
++
++// Platform
++#ifdef MSC
++#include <tools/svwin.h>
++#include <svsys.h>
++#endif
++
++#include <vcl/salgdi.hxx>
++
++#include <unicode/uchar.h>
++#include <unicode/ubidi.h>
++#include <unicode/uscript.h>
++
++// Graphite Libraries (must be after vcl headers on windows)
++#include <graphite/GrClient.h>
++#include <graphite/Font.h>
++#include <graphite/ITextSource.h>
++#include <graphite/Segment.h>
++#include <graphite/SegmentPainter.h>
++
++#include <vcl/graphite_layout.hxx>
++#include <vcl/graphite_features.hxx>
++#include "graphite_textsrc.hxx"
++
++
++// Module private type definitions and forward declarations.
++//
++// Module private names.
++//
++
++#ifdef GRLAYOUT_DEBUG
++FILE * grLogFile = NULL;
++FILE * grLog()
++{
++#ifdef MSC
++	std::string logFileName(getenv("TEMP"));
++	logFileName.append("\\graphitelayout.log");
++    if (grLogFile == NULL) grLogFile = fopen(logFileName.c_str(),"w");
++    else fflush(grLogFile);
++    return grLogFile;
++#else
++    return stdout;
++#endif
++}
++#endif
++
++#ifdef GRCACHE
++#include <vcl/graphite_cache.hxx>
++#endif
++
++
++namespace
++{
++    typedef std::pair<gr::GlyphIterator, gr::GlyphIterator>       glyph_range_t;
++    typedef std::pair<gr::GlyphSetIterator, gr::GlyphSetIterator> glyph_set_range_t;
++
++    inline long round(const float n) {
++        return long(n + (n < 0 ? -0.5 : 0.5));
++    }
++
++
++    template<typename T>
++    inline bool in_range(const T i, const T b, const T e) {
++        return !(b > i) && i < e;
++    }
++
++
++    template<typename T>
++    inline bool is_subrange(const T sb, const T se, const T b, const T e) {
++        return !(b > sb || se > e);
++    }
++
++
++    template<typename T>
++    inline bool is_subrange(const std::pair<T, T> &s, const T b, const T e) {
++        return is_subrange(s.first, s.second, b, e);
++    }
++
++    int findSameDirLimit(const xub_Unicode* buffer, int charCount, bool rtl)
++    {
++        UErrorCode status = U_ZERO_ERROR;
++        UBiDi *ubidi = ubidi_openSized(charCount, 0, &status);
++        int limit = 0;
++        ubidi_setPara(ubidi, buffer, charCount,
++            (rtl)?UBIDI_DEFAULT_RTL:UBIDI_DEFAULT_LTR, NULL, &status);
++        UBiDiLevel level = 0;
++        ubidi_getLogicalRun(ubidi, 0, &limit, &level);
++        ubidi_close(ubidi);
++        if ((rtl && !(level & 1)) || (!rtl && (level & 1)))
++        {
++            limit = 0;
++        }
++        return limit;
++    }
++
++} // namespace
++
++
++
++// Impementation of the GraphiteLayout::Glyphs container class.
++//    This is an extended vector class with methods added to enable
++//        o Correctly filling with glyphs.
++//        o Querying clustering relationships.
++//        o manipulations that affect neighouring glyphs.
++
++const int GraphiteLayout::EXTRA_CONTEXT_LENGTH = 10;
++#ifdef GRCACHE
++GraphiteCacheHandler GraphiteCacheHandler::instance;
++#endif
++
++// The Graphite glyph stream is really a sequence of glyph attachment trees
++//  each rooted at a non-attached base glyph.  fill_from walks the glyph stream
++//  find each non-attached base glyph and calls append to record them as a
++//  sequence of clusters.
++void
++GraphiteLayout::Glyphs::fill_from(gr::Segment & rSegment, ImplLayoutArgs &rArgs,
++    bool bRtl, long &rWidth, float fScaling, std::vector<int> & rChar2Base, std::vector<int> & rGlyph2Char, std::vector<int> & rCharDxs)
++{
++    // Create a glyph item for each of the glyph and append it to the base class glyph list.
++    typedef std::pair< gr::GlyphSetIterator, gr::GlyphSetIterator > GrGlyphSet;
++    int nChar = rArgs.mnEndCharPos - rArgs.mnMinCharPos;
++    glyph_range_t iGlyphs = rSegment.glyphs();
++    int nGlyphs = iGlyphs.second - iGlyphs.first;
++    gr::GlyphIterator prevBase = iGlyphs.second;
++    float fMinX = rSegment.advanceWidth();
++    float fMaxX = 0.0f;
++    rGlyph2Char.assign(nGlyphs, -1);
++    long nDxOffset = 0;
++    int nGlyphIndex = (bRtl)? (nGlyphs - 1) : 0;
++    // OOo always expects the glyphs in ltr order
++    int nDelta = (bRtl)? -1 : 1;
++
++    int nLastGlyph = (bRtl)? nGlyphs - 1: 0;
++    int nNextChar = (bRtl)? (rSegment.stopCharacter() - 1) : rSegment.startCharacter();//rArgs.mnMinCharPos;
++    // current glyph number (Graphite glyphs)
++    //int currGlyph = 0;
++    int nFirstCharInCluster = nNextChar;
++    int nFirstGlyphInCluster = nLastGlyph;
++
++    // ltr first char in cluster is lowest, same is true for rtl
++    // ltr first glyph in cluster is lowest, rtl first glyph is highest
++
++    // loop over the glyphs determining which characters are linked to them
++    gr::GlyphIterator gi;
++    for (gi = iGlyphs.first + nGlyphIndex;
++         nGlyphIndex >= 0 && nGlyphIndex < nGlyphs;
++         nGlyphIndex+= nDelta, gi = iGlyphs.first + nGlyphIndex)
++    {
++        gr::GlyphInfo info = (*gi);
++#ifdef GRLAYOUT_DEBUG
++        fprintf(grLog(),"Glyph %d %f,%f\n", (int)info.logicalIndex(), info.origin(), info.yOffset());
++#endif
++        // the last character associated with this glyph is after
++        // our current cluster buffer position
++        if ((bRtl && ((signed)info.firstChar() <= nNextChar)) ||
++            (!bRtl && ((signed)info.lastChar() >= nNextChar)))
++        {
++            if ((bRtl && nGlyphIndex < nLastGlyph) ||
++                (!bRtl && nGlyphIndex > nLastGlyph))
++            {
++                // this glyph is after the previous one left->right
++                // if insertion is allowed before it then we are in a
++                // new cluster
++                int nAttachedBase = (*(info.attachedClusterBase())).logicalIndex();
++                if (!info.isAttached() ||
++                    !in_range(nAttachedBase, nFirstGlyphInCluster, nGlyphIndex))
++                {
++                    if (in_range(nFirstCharInCluster, rArgs.mnMinCharPos, rArgs.mnEndCharPos) &&
++                        nFirstGlyphInCluster != nGlyphIndex)
++                    {
++                        std::pair <float,float> aBounds =
++                            appendCluster(rSegment, rArgs, bRtl, nFirstCharInCluster,
++                            nNextChar, nFirstGlyphInCluster, nGlyphIndex, fScaling,
++                            rChar2Base, rGlyph2Char, rCharDxs, nDxOffset);
++                        fMinX = std::min(aBounds.first, fMinX);
++                        fMaxX = std::max(aBounds.second, fMaxX);
++                    }
++                    nFirstCharInCluster = (bRtl)? info.lastChar() : info.firstChar();
++                    nFirstGlyphInCluster = nGlyphIndex;
++                }
++                nLastGlyph = (bRtl)? std::min(nGlyphIndex, nAttachedBase) :
++                    std::max(nGlyphIndex, nAttachedBase);
++            }
++            // loop over chacters associated with this glyph and characters
++            // between nextChar and the last character associated with this glyph
++            // giving them the current cluster id.  This allows for character /glyph
++            // order reversal.
++            // For each character we do a reverse glyph id look up
++            // and store the glyph id with the highest logical index in nLastGlyph
++            while ((bRtl && ((signed)info.firstChar() <= nNextChar)) ||
++                   (!bRtl && (signed)info.lastChar() >= nNextChar))
++            {
++                GrGlyphSet charGlyphs = rSegment.charToGlyphs(nNextChar);
++                nNextChar += nDelta;
++                gr::GlyphSetIterator gj = charGlyphs.first;
++                while (gj != charGlyphs.second)
++                {
++                    nLastGlyph = (bRtl)? min(nLastGlyph, (signed)(*gj).logicalIndex()) : max(nLastGlyph, (signed)(*gj).logicalIndex());
++                    ++gj;
++                }
++            }
++            // Loop over attached glyphs and make sure they are all in the cluster since you
++            // can have glyphs attached with another base glyph in between
++            glyph_set_range_t iAttached = info.attachedClusterGlyphs();
++            for (gr::GlyphSetIterator agi = iAttached.first; agi != iAttached.second; ++agi)
++            {
++                nLastGlyph = (bRtl)? min(nLastGlyph, (signed)(*agi).logicalIndex()) : max(nLastGlyph, (signed)(*agi).logicalIndex());
++            }
++
++            // if this is a rtl attached glyph, then we need to include its
++            // base in the cluster, which will have a lower graphite index
++            if (bRtl)
++            {
++                if ((signed)info.attachedClusterBase()->logicalIndex() < nLastGlyph)
++                {
++                    nLastGlyph = info.attachedClusterBase()->logicalIndex();
++                }
++            }
++        }
++
++        // it is possible for the lastChar to be after nextChar and
++        // firstChar to be before the nFirstCharInCluster in rare
++        // circumstances e.g. Myanmar word for cemetery
++        if ((bRtl && ((signed)info.lastChar() > nFirstCharInCluster)) ||
++            (!bRtl && ((signed)info.firstChar() < nFirstCharInCluster)))
++        {
++            nFirstCharInCluster = info.firstChar();
++        }
++    }
++    // process last cluster
++    if (in_range(nFirstCharInCluster, rArgs.mnMinCharPos, rArgs.mnEndCharPos) &&
++        nFirstGlyphInCluster != nGlyphIndex)
++    {
++        std::pair <float,float> aBounds =
++            appendCluster(rSegment, rArgs, bRtl, nFirstCharInCluster, nNextChar,
++                          nFirstGlyphInCluster, nGlyphIndex, fScaling,
++                          rChar2Base, rGlyph2Char, rCharDxs, nDxOffset);
++        fMinX = std::min(aBounds.first, fMinX);
++        fMaxX = std::max(aBounds.second, fMaxX);
++    }
++    long nXOffset = round(fMinX * fScaling);
++    rWidth = round(fMaxX * fScaling) - nXOffset + nDxOffset;
++	if (rWidth < 0)
++	{
++		// This can happen when there was no base inside the range
++		rWidth = 0;
++	}
++    // fill up non-base char dx with cluster widths from previous base glyph
++    if (bRtl)
++    {
++        if (rCharDxs[nChar-1] == -1)
++            rCharDxs[nChar-1] = 0;
++        else
++            rCharDxs[nChar-1] -= nXOffset;
++        for (int i = nChar - 2; i >= 0; i--)
++        {
++            if (rCharDxs[i] == -1) rCharDxs[i] = rCharDxs[i+1];
++            else rCharDxs[i] -= nXOffset;
++        }
++    }
++    else
++    {
++        if (rCharDxs[0] == -1)
++            rCharDxs[0] = 0;
++        else
++            rCharDxs[0] -= nXOffset;
++        for (int i = 1; i < nChar; i++)
++        {
++            if (rCharDxs[i] == -1) rCharDxs[i] = rCharDxs[i-1];
++            else rCharDxs[i] -= nXOffset;
++        }
++    }
++#ifdef GRLAYOUT_DEBUG
++    fprintf(grLog(),"Glyphs xOff%ld dropDx%ld w%ld\n", nXOffset, nDxOffset, rWidth);
++#endif
++    // remove offset due to context if there is one
++    if (nXOffset != 0)
++    {
++        for (size_t i = 0; i < size(); i++)
++            (*this)[i].maLinearPos.X() -= nXOffset;
++    }
++}
++
++std::pair<float,float> GraphiteLayout::Glyphs::appendCluster(gr::Segment & rSeg,
++    ImplLayoutArgs & rArgs, bool bRtl, int nFirstCharInCluster, int nNextChar,
++    int nFirstGlyphInCluster, int nNextGlyph, float fScaling,
++    std::vector<int> & rChar2Base, std::vector<int> & rGlyph2Char,
++    std::vector<int> & rCharDxs, long & rDXOffset)
++{
++    glyph_range_t iGlyphs = rSeg.glyphs();
++    int nGlyphs = iGlyphs.second - iGlyphs.first;
++    int nDelta = (bRtl)? -1 : 1;
++    gr::GlyphInfo aFirstGlyph = *(iGlyphs.first + nFirstGlyphInCluster);
++    std::pair <float, float> aBounds;
++    aBounds.first = aFirstGlyph.origin();
++    aBounds.second = aFirstGlyph.origin();
++    // before we add the glyphs to this vector, we record the
++    // glyph's index in the vector (which is not the same as
++    // the Segment's glyph index!)
++    assert(size() < rGlyph2Char.size());
++    rChar2Base[nFirstCharInCluster-rArgs.mnMinCharPos] = size();
++    rGlyph2Char[size()] = nFirstCharInCluster;
++    bool bBaseGlyph = true;
++    for (int j = nFirstGlyphInCluster;
++        j != nNextGlyph; j += nDelta)
++    {
++        long nNextOrigin;
++        float fNextOrigin;
++        gr::GlyphInfo aGlyph = *(iGlyphs.first + j);
++        if (j + nDelta >= nGlyphs || j + nDelta < 0) // at rhs ltr,rtl
++        {
++            fNextOrigin = rSeg.advanceWidth();
++            nNextOrigin = round(rSeg.advanceWidth() * fScaling + rDXOffset);
++            aBounds.second = std::max(rSeg.advanceWidth(), aBounds.second);
++        }
++        else
++        {
++            gr::GlyphInfo aNextGlyph = *(iGlyphs.first + j + nDelta);
++            fNextOrigin = std::max(aNextGlyph.attachedClusterBase()->origin(), aNextGlyph.origin());
++            aBounds.second = std::max(fNextOrigin, aBounds.second);
++            nNextOrigin = round(fNextOrigin * fScaling + rDXOffset);
++        }
++        aBounds.first = std::min(aGlyph.origin(), aBounds.first);
++        if ((signed)aGlyph.firstChar() < rArgs.mnEndCharPos &&
++            (signed)aGlyph.firstChar() >= rArgs.mnMinCharPos)
++        {
++            rCharDxs[aGlyph.firstChar()-rArgs.mnMinCharPos] = nNextOrigin;
++        }
++        if ((signed)aGlyph.attachedClusterBase()->logicalIndex() == j)
++        {
++            append(rSeg, rArgs, aGlyph, fNextOrigin, fScaling, rChar2Base, rGlyph2Char, rCharDxs, rDXOffset, bBaseGlyph);
++            bBaseGlyph = false;
++        }
++    }
++    // from the point of view of the dx array, the xpos is
++    // the origin of the first glyph of the next cluster ltr
++    // rtl it is the origin of the 1st glyph of the cluster
++    long nXPos = (bRtl)?
++        round(aFirstGlyph.attachedClusterBase()->origin() * fScaling) + rDXOffset :
++        round(aBounds.second * fScaling) + rDXOffset;
++    // force the last char in range to have the width of the cluster
++    if (bRtl)
++    {
++        for (int n = nNextChar + 1; n <= nFirstCharInCluster; n++)
++        {
++            if ((n < rArgs.mnEndCharPos) && (n >= rArgs.mnMinCharPos))
++                rCharDxs[n-rArgs.mnMinCharPos] = nXPos;
++        }
++    }
++    else
++    {
++        for (int n = nNextChar - 1; n >= nFirstCharInCluster; n--)
++        {
++            if (n < rArgs.mnEndCharPos && n >= rArgs.mnMinCharPos)
++                rCharDxs[n-rArgs.mnMinCharPos] = nXPos;
++        }
++    }
++#ifdef GRLAYOUT_DEBUG
++    fprintf(grLog(),"Cluster g[%d-%d) c[%d-%d)%x x%ld y%f\n", nFirstGlyphInCluster, nNextGlyph, nFirstCharInCluster, nNextChar, rArgs.mpStr[nFirstCharInCluster], nXPos, aFirstGlyph.yOffset());
++#endif
++    return aBounds;
++}
++
++// append walks an attachment tree, flattening it, and converting it into a
++// sequence of GlyphItem objects which we can later manipulate.
++void
++GraphiteLayout::Glyphs::append(gr::Segment &segment, ImplLayoutArgs &args, gr::GlyphInfo & gi, float nextGlyphOrigin, float scaling, std::vector<int> & rChar2Base, std::vector<int> & rGlyph2Char, std::vector<int> & rCharDxs, long & rDXOffset, bool bIsBase)
++{
++    float nextOrigin = nextGlyphOrigin;
++    int firstChar = std::min(gi.firstChar(), gi.lastChar());
++    assert(size() < rGlyph2Char.size());
++    if (!bIsBase) rGlyph2Char[size()] = firstChar;
++    // is the next glyph attached or in the next cluster?
++    glyph_set_range_t iAttached = gi.attachedClusterGlyphs();
++    if (iAttached.first != iAttached.second)
++    {
++        nextOrigin = iAttached.first->origin();
++    }
++    long glyphId = gi.glyphID();
++    long deltaOffset = 0;
++    int glyphWidth = round(nextOrigin * scaling) - round(gi.origin() * scaling);
++#ifdef GRLAYOUT_DEBUG
++    fprintf(grLog(),"c%d g%d gWidth%d x%f ", firstChar, (int)gi.logicalIndex(), glyphWidth, nextOrigin);
++#endif
++    if (glyphId == 0)
++    {
++        args.NeedFallback(
++            firstChar,
++            gr::RightToLeftDir(gr::DirCode(gi.directionality())));
++        if( (SAL_LAYOUT_FOR_FALLBACK & args.mnFlags ))
++        {
++            glyphId = GF_DROPPED;
++            deltaOffset -= glyphWidth;
++            glyphWidth = 0;
++        }
++    }
++    else if(args.mnFlags & SAL_LAYOUT_FOR_FALLBACK)
++    {
++#ifdef GRLAYOUT_DEBUG
++        fprintf(grLog(),"fallback c%d %x in run %d\n", firstChar, args.mpStr[firstChar],
++            args.maRuns.PosIsInAnyRun(firstChar));
++#endif
++        // glyphs that aren't requested for fallback will be taken from base
++        // layout, so mark them as dropped (should this wait until Simplify(false) is called?)
++        if (!args.maRuns.PosIsInAnyRun(firstChar) &&
++            in_range(firstChar, args.mnMinCharPos, args.mnEndCharPos))
++        {
++            glyphId = GF_DROPPED;
++            deltaOffset -= glyphWidth;
++            glyphWidth = 0;
++        }
++    }
++    // append this glyph.
++    long nGlyphFlags = bIsBase ? 0 : GlyphItem::IS_IN_CLUSTER;
++    // directionality seems to be unreliable
++    //nGlyphFlags |= gr::RightToLeftDir(gr::DirCode(gi.attachedClusterBase()->directionality())) ? GlyphItem::IS_RTL_GLYPH : 0;
++    nGlyphFlags |= (gi.directionLevel() & 0x1)? GlyphItem::IS_RTL_GLYPH : 0;
++    GlyphItem aGlyphItem(size(),//gi.logicalIndex(),
++        glyphId,
++        Point(round(gi.origin() * scaling + rDXOffset),
++            round((-gi.yOffset() * scaling) - segment.AscentOffset()* scaling)),
++        nGlyphFlags,
++        glyphWidth);
++    aGlyphItem.mnOrigWidth = round(gi.advanceWidth() * scaling);
++    push_back(aGlyphItem);
++
++    // update the offset if this glyph was dropped
++    rDXOffset += deltaOffset;
++
++    // Recursively apply append all the attached glyphs.
++    for (gr::GlyphSetIterator agi = iAttached.first; agi != iAttached.second; ++agi)
++    {
++        if (agi + 1 == iAttached.second)
++            append(segment, args, *agi, nextGlyphOrigin, scaling, rChar2Base, rGlyph2Char,rCharDxs, rDXOffset, false);
++        else
++            append(segment, args, *agi, (agi + 1)->origin(), scaling, rChar2Base, rGlyph2Char, rCharDxs, rDXOffset, false);
++    }
++}
++
++//
++// An implementation of the SalLayout interface to enable Graphite enabled fonts to be used.
++//
++GraphiteLayout::GraphiteLayout(const gr::Font & font, const grutils::GrFeatureParser * pFeatures) throw()
++  : mpTextSrc(0),
++    mrFont(font),
++    mnWidth(0),
++    mfScaling(1.0),
++    mpFeatures(pFeatures)
++{
++    // Line settings can have subtle affects on space handling
++    // since we don't really know whether it is the end of a line or just a run
++    // in the middle, it is hard to know what to set them to.
++    // If true, it can cause end of line spaces to be hidden e.g. Doulos SIL
++    maLayout.setStartOfLine(false);
++    maLayout.setEndOfLine(false);
++//    maLayout.setDumbFallback(false);
++    // trailing ws doesn't seem to always take affect if end of line is true
++    maLayout.setTrailingWs(gr::ktwshAll);
++#ifdef GRLAYOUT_DEBUG
++    gr::ScriptDirCode aDirCode = font.getSupportedScriptDirections();
++    fprintf(grLog(),"GraphiteLayout scripts %x %lx\n", aDirCode, long(this));
++#endif
++}
++
++
++GraphiteLayout::~GraphiteLayout() throw()
++{
++    clear();
++    // the features are owned by the platform layers
++    mpFeatures = NULL;
++}
++
++void GraphiteLayout::clear()
++{
++    // Destroy the segment and text source from any previous invocation of
++    // LayoutText
++    mvGlyphs.clear();
++    mvCharDxs.clear();
++    mvChar2BaseGlyph.clear();
++    mvGlyph2Char.clear();
++
++#ifndef GRCACHE
++    delete mpTextSrc;
++#endif
++
++    // Reset the state to the empty state.
++    mpTextSrc=0;
++    mnWidth = 0;
++    // Don't reset the scaling, because it is set before LayoutText
++}
++
++// This method shouldn't be called on windows, since it needs the dc reset
++bool GraphiteLayout::LayoutText(ImplLayoutArgs & rArgs)
++{
++#ifdef GRCACHE
++    GrSegRecord * pSegRecord = NULL;
++    gr::Segment * pSegment = CreateSegment(rArgs, &pSegRecord);
++    if (!pSegment)
++       return false;
++
++    // layout the glyphs as required by OpenOffice
++    bool success = LayoutGlyphs(rArgs, pSegment, pSegRecord);
++
++    if (pSegRecord) pSegRecord->unlock();
++    else delete pSegment;
++#else
++    gr::Segment * pSegment = CreateSegment(rArgs);
++    bool success = LayoutGlyphs(rArgs, pSegment);
++    delete pSegment;
++#endif
++    return success;
++}
++
++#ifdef GRCACHE
++class GrFontHasher : public gr::Font
++{
++public:
++    GrFontHasher(const gr::Font & aFont) : gr::Font(aFont), mrRealFont(const_cast<gr::Font&>(aFont)) {};
++    ~GrFontHasher(){};
++    virtual bool bold() { return mrRealFont.bold(); };
++    virtual bool italic() { return mrRealFont.italic(); };
++    virtual float ascent()  { return mrRealFont.ascent(); };
++    virtual float descent()  { return mrRealFont.descent(); };
++    virtual float height()  { return mrRealFont.height(); };
++    virtual gr::Font* copyThis() { return mrRealFont.copyThis(); };
++    virtual unsigned int getDPIx() { return mrRealFont.getDPIx(); };
++    virtual unsigned int getDPIy() { return mrRealFont.getDPIy(); };
++    virtual const void* getTable(gr::fontTableId32 nId, size_t* nSize)
++    { return mrRealFont.getTable(nId,nSize); }
++    virtual void getFontMetrics(float*pA, float*pB, float*pC) { mrRealFont.getFontMetrics(pA,pB,pC); };
++
++    sal_Int32 hashCode(const grutils::GrFeatureParser * mpFeatures)
++    {
++        // is this sufficient?
++        std::wstring aFace;
++        bool bBold;
++        bool bItalic;
++        UniqueCacheInfo(aFace, bBold, bItalic);
++        sal_Unicode uName[32]; // max length used in gr::Font
++        // Note: graphite stores font names as UTF-16 even if wchar_t is 32bit
++        // this conversion should be OK.
++        for (size_t i = 0; i < aFace.size() && i < 32; i++)
++        {
++            uName[i] = aFace[i];
++        }
++        size_t iSize = aFace.size();
++        if (0 == iSize) return 0;
++        sal_Int32 hash = rtl_ustr_hashCode_WithLength(uName, iSize);
++        hash ^= static_cast<sal_Int32>(height());
++        hash |= (bBold)? 0x1000000 : 0;
++        hash |= (bItalic)? 0x2000000 : 0;
++        if (mpFeatures)
++            hash ^= mpFeatures->hashCode();
++#ifdef GRLAYOUT_DEBUG
++        fprintf(grLog(), "font hash %x size %f\n", (int)hash, height());
++#endif
++        return hash;
++    };
++
++private:
++    gr::Font & mrRealFont;
++};
++#endif
++
++#ifdef GRCACHE
++gr::Segment * GraphiteLayout::CreateSegment(ImplLayoutArgs& rArgs, GrSegRecord ** pSegRecord)
++#else
++gr::Segment * GraphiteLayout::CreateSegment(ImplLayoutArgs& rArgs)
++#endif
++{
++    assert(rArgs.mnLength >= 0);
++
++    gr::Segment * pSegment = NULL;
++
++    // Set the SalLayouts values to be the inital ones.
++    SalLayout::AdjustLayout(rArgs);
++    // TODO check if this is needed
++    if (mnUnitsPerPixel > 1)
++        mfScaling = 1.0f / mnUnitsPerPixel;
++
++    // Clear out any previous buffers
++    clear();
++    bool bRtl = mnLayoutFlags & SAL_LAYOUT_BIDI_RTL;
++    try
++    {
++        // Don't set RTL if font doesn't support it otherwise it forces rtl on
++        // everything
++        if (bRtl && (mrFont.getSupportedScriptDirections() & gr::kfsdcHorizRtl))
++            maLayout.setRightToLeft(bRtl);
++
++#ifdef GRCACHE
++        GrFontHasher hasher(mrFont);
++        sal_Int32 aFontHash = hasher.hashCode(mpFeatures);
++        GraphiteSegmentCache * pCache =
++            (GraphiteCacheHandler::instance).getCache(aFontHash);
++        if (pCache)
++        {
++            *pSegRecord = pCache->getSegment(rArgs, bRtl);
++            if (*pSegRecord)
++            {
++                pSegment = (*pSegRecord)->getSegment();
++                mpTextSrc = (*pSegRecord)->getTextSrc();
++                maLayout.setRightToLeft((*pSegRecord)->isRtl());
++                if (rArgs.mpStr != mpTextSrc->getLayoutArgs().mpStr ||
++                    rArgs.mnMinCharPos != mpTextSrc->getLayoutArgs().mnMinCharPos ||
++                    rArgs.mnEndCharPos != mpTextSrc->getLayoutArgs().mnEndCharPos ||
++                    (SAL_LAYOUT_FOR_FALLBACK & rArgs.mnFlags) )
++                {
++                    (*pSegRecord)->clearVectors();
++                }
++                mpTextSrc->switchLayoutArgs(rArgs);
++                return pSegment;
++            }
++        }
++#endif
++
++        // Context is often needed beyond the specified end, however, we don't
++        // want it if there has been a direction change, since it is hard
++        // to tell between reordering within one direction and multi-directional
++        // text.
++        const int  segCharLimit = min(rArgs.mnLength, mnEndCharPos + EXTRA_CONTEXT_LENGTH);
++        int limit = rArgs.mnEndCharPos;
++        if (segCharLimit > limit)
++        {
++            limit += findSameDirLimit(rArgs.mpStr + rArgs.mnEndCharPos,
++                segCharLimit - rArgs.mnEndCharPos, bRtl);
++        }
++
++        // Create a new TextSource object for the engine.
++        mpTextSrc = new TextSourceAdaptor(rArgs, limit);
++        if (mpFeatures) mpTextSrc->setFeatures(mpFeatures);
++
++        pSegment = new gr::RangeSegment((gr::Font *)&mrFont, mpTextSrc, &maLayout, mnMinCharPos, limit);
++        if (pSegment != NULL)
++        {
++#ifdef GRLAYOUT_DEBUG
++            fprintf(grLog(),"Gr::LayoutText %d-%d, context %d,len%d rtl%d/%d scaling %f\n", rArgs.mnMinCharPos,
++               rArgs.mnEndCharPos, limit, rArgs.mnLength, maLayout.rightToLeft(), pSegment->rightToLeft(), mfScaling);
++#endif
++#ifdef GRCACHE
++            // on a new segment rightToLeft should be correct
++            *pSegRecord = pCache->cacheSegment(mpTextSrc, pSegment, pSegment->rightToLeft());
++#endif
++        }
++        else
++        {
++            clear();
++            return NULL;
++        }
++    }
++    catch (...)
++    {
++        clear();  // destroy the text source and any partially built segments.
++        return NULL;
++    }
++    return pSegment;
++}
++
++#ifdef GRCACHE
++bool GraphiteLayout::LayoutGlyphs(ImplLayoutArgs& rArgs, gr::Segment * pSegment, GrSegRecord * pSegRecord)
++#else
++bool GraphiteLayout::LayoutGlyphs(ImplLayoutArgs& rArgs, gr::Segment * pSegment)
++#endif
++{
++#ifdef GRCACHE
++#ifdef GRCACHE_REUSE_VECTORS
++    // if we have an exact match, then we can reuse the glyph vectors from before
++    if (pSegRecord && (pSegRecord->glyphs().size() > 0) &&
++        !(SAL_LAYOUT_FOR_FALLBACK & rArgs.mnFlags) )
++    {
++        mnWidth = pSegRecord->width();
++        mvGlyphs = pSegRecord->glyphs();
++        mvCharDxs = pSegRecord->charDxs();
++        mvChar2BaseGlyph = pSegRecord->char2BaseGlyph();
++        mvGlyph2Char = pSegRecord->glyph2Char();
++        return true;
++    }
++#endif
++#endif
++    // Calculate the initial character dxs.
++    mvCharDxs.assign(mnEndCharPos - mnMinCharPos, -1);
++    mvChar2BaseGlyph.assign(mnEndCharPos - mnMinCharPos, -1);
++    mnWidth = 0;
++    if (mvCharDxs.size() > 0)
++    {
++        // Discover all the clusters.
++        try
++        {
++            // Note: we use the layout rightToLeft() because in cached segments
++            // rightToLeft() may no longer be valid if the engine has been run
++            // ltr since the segment was created.
++#ifdef GRCACHE
++			bool bRtl = pSegRecord? pSegRecord->isRtl() : pSegment->rightToLeft();
++#else
++			bool bRtl = pSegment->rightToLeft();
++#endif
++            mvGlyphs.fill_from(*pSegment, rArgs, bRtl,
++                mnWidth, mfScaling, mvChar2BaseGlyph, mvGlyph2Char, mvCharDxs);
++
++            if (bRtl)
++            {
++                // not needed for adjacent differences, but for mouse clicks to char
++                std::transform(mvCharDxs.begin(), mvCharDxs.end(), mvCharDxs.begin(),
++                    std::bind1st(std::minus<long>(), mnWidth));
++                // fixup last dx to ensure it always equals the width
++                mvCharDxs[mvCharDxs.size() - 1] = mnWidth;
++            }
++#ifdef GRCACHE
++#ifdef GRCACHE_REUSE_VECTORS
++            if (pSegRecord && rArgs.maReruns.IsEmpty() &&
++                !(SAL_LAYOUT_FOR_FALLBACK & rArgs.mnFlags))
++            {
++                pSegRecord->setGlyphVectors(mnWidth, mvGlyphs, mvCharDxs,
++                                            mvChar2BaseGlyph, mvGlyph2Char);
++            }
++#endif
++#endif
++        }
++        catch (std::exception e)
++        {
++#ifdef GRLAYOUT_DEBUG
++            fprintf(grLog(),"LayoutGlyphs failed %s\n", e.what());
++#endif
++            return false;
++        }
++        catch (...)
++        {
++#ifdef GRLAYOUT_DEBUG
++            fprintf(grLog(),"LayoutGlyphs failed with exception");
++#endif
++            return false;
++        }
++	}
++    else
++    {
++        mnWidth = 0;
++    }
++    return true;
++}
++
++int GraphiteLayout::GetTextBreak(long maxmnWidth, long char_extra, int factor) const
++{
++    // Adjust maxmnWidth so FindNextBreakPoint returns a sensible answer.
++    maxmnWidth -= (mnEndCharPos-mnMinCharPos-1)*char_extra;  // extra character spacing.
++    maxmnWidth /= factor;                                    // scaling factor.
++
++    // Ask the segment for the nearest whole letter break for the width.
++    //float width;
++    float targetWidth = maxmnWidth/mfScaling;
++    // return quickly if this segment is narrower than the target width
++    // (sometimes graphite doesn't seem to realise this!)
++    if (targetWidth > mnWidth)
++        return STRING_LEN;
++    //int    nBreak = mpSegment->findNextBreakPoint(mnMinCharPos,
++    //        gr::klbWordBreak, gr::klbLetterBreak, targetWidth, &width);
++
++    // LineFillSegment seems to give better results that findNextBreakPoint
++    // though it may be slower
++    gr::LayoutEnvironment aLE;
++    gr::LineFillSegment lineSeg(const_cast<gr::Font *>(&mrFont), mpTextSrc, &aLE,
++                                mnMinCharPos, mpTextSrc->getContextLength(),
++                                targetWidth);
++    int nBreak = lineSeg.stopCharacter();
++
++    if (nBreak > mnEndCharPos) nBreak = STRING_LEN;
++    else if (nBreak < mnMinCharPos) nBreak = mnMinCharPos;
++    return nBreak;
++}
++
++
++long GraphiteLayout::FillDXArray( sal_Int32* pDXArray ) const
++{
++    if (mnEndCharPos == mnMinCharPos)
++        // Then we must be zero width!
++        return 0;
++
++    if (pDXArray)
++    {
++        for (size_t i = 0; i < mvCharDxs.size(); i++)
++        {
++            assert((mvChar2BaseGlyph[i] >= -1) && (mvChar2BaseGlyph[i] < (signed)mvGlyphs.size()));
++            if (mvChar2BaseGlyph[i] != -1 &&
++                mvGlyphs[mvChar2BaseGlyph[i]].mnGlyphIndex == GF_DROPPED)
++            {
++                // when used in MultiSalLayout::GetTextBreak dropped glyphs
++                // must have zero width
++                pDXArray[i] = 0;
++            }
++            else
++            {
++                pDXArray[i] = mvCharDxs[i];
++                if (i > 0) pDXArray[i] -= mvCharDxs[i-1];
++            }
++#ifdef GRLAYOUT_DEBUG
++            fprintf(grLog(),"%d,%d,%ld ", (int)i, (int)mvCharDxs[i], pDXArray[i]);
++#endif
++        }
++        //std::adjacent_difference(mvCharDxs.begin(), mvCharDxs.end(), pDXArray);
++        //for (size_t i = 0; i < mvCharDxs.size(); i++)
++        //    fprintf(grLog(),"%d,%d,%d ", (int)i, (int)mvCharDxs[i], pDXArray[i]);
++        //fprintf(grLog(),"FillDX %ld,%d\n", mnWidth, std::accumulate(pDXArray, pDXArray + mvCharDxs.size(), 0));
++    }
++#ifdef GRLAYOUT_DEBUG
++    fprintf(grLog(),"FillDXArray %d-%d,%d=%ld\n", mnMinCharPos, mnEndCharPos, (int)mpTextSrc->getLength(), mnWidth);
++#endif
++    return mnWidth;
++}
++
++
++void  GraphiteLayout::AdjustLayout(ImplLayoutArgs& rArgs)
++{
++    SalLayout::AdjustLayout(rArgs);
++
++    if(rArgs.mpDXArray)
++    {
++        std::vector<int> vDeltaWidths(mvGlyphs.size(), 0);
++        ApplyDXArray(rArgs, vDeltaWidths);
++
++        if( (mnLayoutFlags & SAL_LAYOUT_BIDI_RTL) &&
++           !(rArgs.mnFlags & SAL_LAYOUT_FOR_FALLBACK) )
++        {
++            // check if this is a kashida script
++            bool bKashidaScript = false;
++            for (int i = rArgs.mnMinCharPos; i < rArgs.mnEndCharPos; i++)
++            {
++                UErrorCode aStatus = U_ZERO_ERROR;
++                UScriptCode scriptCode = uscript_getScript(rArgs.mpStr[i], &aStatus);
++                if (scriptCode == USCRIPT_ARABIC || scriptCode == USCRIPT_SYRIAC)
++                {
++                    bKashidaScript = true;
++                    break;
++                }
++            }
++            int nKashidaWidth = 0;
++            int nKashidaIndex = getKashidaGlyph(nKashidaWidth);
++            if( nKashidaIndex != 0 && bKashidaScript)
++            {
++                kashidaJustify( vDeltaWidths, nKashidaIndex, nKashidaWidth );
++            }
++        }
++    }
++}
++
++
++void GraphiteLayout::ApplyDXArray(ImplLayoutArgs &args, std::vector<int> & rDeltaWidth)
++{
++    const size_t nChars = args.mnEndCharPos - args.mnMinCharPos;
++    if (nChars == 0) return;
++
++#ifdef GRLAYOUT_DEBUG
++    for (size_t iDx = 0; iDx < mvCharDxs.size(); iDx++)
++         fprintf(grLog(),"%d,%d,%ld ", (int)iDx, (int)mvCharDxs[iDx], args.mpDXArray[iDx]);
++    fprintf(grLog(),"ApplyDx\n");
++#endif
++    bool bRtl = mnLayoutFlags & SAL_LAYOUT_BIDI_RTL;
++    int nXOffset = 0;
++    if (bRtl)
++    {
++        nXOffset = args.mpDXArray[nChars - 1] - mvCharDxs[nChars - 1];
++    }
++    int nPrevClusterGlyph = (bRtl)? mvGlyphs.size() : -1;
++    int nPrevClusterLastChar = -1;
++    for (size_t i = 0; i < nChars; i++)
++    {
++        if (mvChar2BaseGlyph[i] > -1 && mvChar2BaseGlyph[i] != nPrevClusterGlyph)
++        {
++            assert((mvChar2BaseGlyph[i] > -1) && (mvChar2BaseGlyph[i] < (signed)mvGlyphs.size()));
++            GlyphItem & gi = mvGlyphs[mvChar2BaseGlyph[i]];
++            if (!gi.IsClusterStart())
++                continue;
++
++            // find last glyph of this cluster
++            size_t j = i + 1;
++            int nLastChar = i;
++            int nLastGlyph = mvChar2BaseGlyph[i];
++            for (; j < nChars; j++)
++            {
++                assert((mvChar2BaseGlyph[j] >= -1) && (mvChar2BaseGlyph[j] < (signed)mvGlyphs.size()));
++                if (mvChar2BaseGlyph[j] != -1 && mvGlyphs[mvChar2BaseGlyph[j]].IsClusterStart())
++                {
++                    nLastGlyph = mvChar2BaseGlyph[j] + ((bRtl)? 1 : -1);
++                    nLastChar = j - 1;
++                    break;
++                }
++            }
++            if (nLastGlyph < 0)
++            {
++                nLastGlyph = mvChar2BaseGlyph[i];
++            }
++            // Its harder to find the last glyph rtl, since the first of
++            // cluster is still on the left so we need to search towards
++            // the previous cluster to the right
++            if (bRtl)
++            {
++                nLastGlyph = mvChar2BaseGlyph[i];
++                while (nLastGlyph + 1 < (signed)mvGlyphs.size() &&
++                       !mvGlyphs[nLastGlyph+1].IsClusterStart())
++                {
++                    ++nLastGlyph;
++                }
++            }
++            if (j == nChars)
++            {
++                nLastChar = nChars - 1;
++                if (!bRtl) nLastGlyph = mvGlyphs.size() - 1;
++            }
++            assert((nLastChar > -1) && (nLastChar < (signed)nChars));
++            long nNewClusterWidth = args.mpDXArray[nLastChar];
++            long nOrigClusterWidth = mvCharDxs[nLastChar];
++            long nDGlyphOrigin = 0;
++            if (nPrevClusterLastChar > - 1)
++            {
++                assert(nPrevClusterLastChar < (signed)nChars);
++                nNewClusterWidth -= args.mpDXArray[nPrevClusterLastChar];
++                nOrigClusterWidth -= mvCharDxs[nPrevClusterLastChar];
++                nDGlyphOrigin = args.mpDXArray[nPrevClusterLastChar] - mvCharDxs[nPrevClusterLastChar];
++            }
++            long nDWidth = nNewClusterWidth - nOrigClusterWidth;
++#ifdef GRLAYOUT_DEBUG
++            fprintf(grLog(), "c%d last glyph %d/%d\n", i, nLastGlyph, mvGlyphs.size());
++#endif
++            assert((nLastGlyph > -1) && (nLastGlyph < (signed)mvGlyphs.size()));
++            mvGlyphs[nLastGlyph].mnNewWidth += nDWidth;
++            if (gi.mnGlyphIndex != GF_DROPPED)
++                mvGlyphs[nLastGlyph].mnNewWidth += nDWidth;
++            else
++                nDGlyphOrigin += nDWidth;
++            // update glyph positions
++            if (bRtl)
++            {
++                for (int n = mvChar2BaseGlyph[i]; n <= nLastGlyph; n++)
++                {
++                    assert((n > - 1) && (n < (signed)mvGlyphs.size()));
++                    mvGlyphs[n].maLinearPos.X() += -nDGlyphOrigin + nXOffset;
++                }
++            }
++            else
++            {
++                for (int n = mvChar2BaseGlyph[i]; n <= nLastGlyph; n++)
++                {
++                    assert((n > - 1) && (n < (signed)mvGlyphs.size()));
++                    mvGlyphs[n].maLinearPos.X() += nDGlyphOrigin + nXOffset;
++                }
++            }
++            rDeltaWidth[mvChar2BaseGlyph[i]] = nDWidth;
++#ifdef GRLAYOUT_DEBUG
++            fprintf(grLog(),"c%d g%d-%d dW%ld-%ld=%ld dX%ld x%ld\t", (int)i, mvChar2BaseGlyph[i], nLastGlyph, nNewClusterWidth, nOrigClusterWidth, nDWidth, nDGlyphOrigin, mvGlyphs[mvChar2BaseGlyph[i]].maLinearPos.X());
++#endif
++            nPrevClusterGlyph = mvChar2BaseGlyph[i];
++            nPrevClusterLastChar = nLastChar;
++            i = nLastChar;
++        }
++    }
++    // Update the dx vector with the new values.
++    std::copy(args.mpDXArray, args.mpDXArray + nChars,
++      mvCharDxs.begin() + (args.mnMinCharPos - mnMinCharPos));
++#ifdef GRLAYOUT_DEBUG
++    fprintf(grLog(),"ApplyDx %ld(%ld)\n", args.mpDXArray[nChars - 1], mnWidth);
++#endif
++    mnWidth = args.mpDXArray[nChars - 1];
++}
++
++void GraphiteLayout::kashidaJustify(std::vector<int>& rDeltaWidths, sal_GlyphId nKashidaIndex, int nKashidaWidth)
++{
++    // skip if the kashida glyph in the font looks suspicious
++    if( nKashidaWidth <= 0 )
++        return;
++
++    // calculate max number of needed kashidas
++    Glyphs::iterator i = mvGlyphs.begin();
++    int nKashidaCount = 0;
++    int nOrigGlyphIndex = -1;
++    int nGlyphIndex = -1;
++    while (i != mvGlyphs.end())
++    {
++        nOrigGlyphIndex++;
++        nGlyphIndex++;
++        // only inject kashidas in RTL contexts
++        if( !(*i).IsRTLGlyph() )
++        {
++            ++i;
++            continue;
++        }
++        // no kashida-injection for blank justified expansion either
++        if( IsSpacingGlyph( (*i).mnGlyphIndex ) )
++        {
++            ++i;
++            continue;
++        }
++        // calculate gap, ignore if too small
++        int nGapWidth = rDeltaWidths[nOrigGlyphIndex];;
++        // worst case is one kashida even for mini-gaps
++        if( 3 * nGapWidth < nKashidaWidth )
++        {
++            ++i;
++            continue;
++        }
++        nKashidaCount = 1 + (nGapWidth / nKashidaWidth);
++#ifdef GRLAYOUT_DEBUG
++        printf("inserting %d kashidas at %ld\n", nKashidaCount, (*i).mnGlyphIndex);
++#endif
++        GlyphItem glyphItem = *i;
++        Point aPos(0, 0);
++        aPos.X() = (*i).maLinearPos.X();
++        GlyphItem newGi(glyphItem.mnCharPos, nKashidaIndex, aPos,
++                GlyphItem::IS_IN_CLUSTER|GlyphItem::IS_RTL_GLYPH, nKashidaWidth);
++        mvGlyphs.reserve(mvGlyphs.size() + nKashidaCount);
++        i = mvGlyphs.begin() + nGlyphIndex;
++        mvGlyphs.insert(i, nKashidaCount, newGi);
++        i = mvGlyphs.begin() + nGlyphIndex;
++        nGlyphIndex += nKashidaCount;
++        // now fix up the kashida positions
++        for (int j = 0; j < nKashidaCount; j++)
++        {
++            (*(i)).maLinearPos.X() -= nGapWidth;
++            nGapWidth -= nKashidaWidth;
++            i++;
++        }
++
++        // fixup rightmost kashida for gap remainder
++        if( nGapWidth < 0 )
++        {
++            if( nKashidaCount <= 1 )
++                nGapWidth /= 2;               // for small gap move kashida to middle
++            (*(i-1)).mnNewWidth += nGapWidth;  // adjust kashida width to gap width
++            (*(i-1)).maLinearPos.X() += nGapWidth;
++        }
++
++        (*i).mnNewWidth = (*i).mnOrigWidth;
++        ++i;
++    }
++
++}
++
++void GraphiteLayout::GetCaretPositions( int nArraySize, sal_Int32* pCaretXArray ) const
++{
++    // For each character except the last discover the caret positions
++    // immediatly before and after that character.
++    // This is used for underlines in the GUI amongst other things.
++    // It may be used from MultiSalLayout, in which case it must take into account
++    // glyphs that have been moved.
++    std::fill(pCaretXArray, pCaretXArray + nArraySize, -1);
++    // the layout method doesn't modify the layout even though it isn't
++    // const in the interface
++    bool bRtl = const_cast<GraphiteLayout*>(this)->maLayout.rightToLeft();
++    int prevBase = -1;
++    long prevClusterWidth = 0;
++    for (int i = 0, nCharSlot = 0; i < nArraySize && nCharSlot < static_cast<int>(mvCharDxs.size()); ++nCharSlot, i+=2)
++    {
++        if (mvChar2BaseGlyph[nCharSlot] != -1)
++        {
++            assert((mvChar2BaseGlyph[nCharSlot] > -1) && (mvChar2BaseGlyph[nCharSlot] < (signed)mvGlyphs.size()));
++            GlyphItem gi = mvGlyphs[mvChar2BaseGlyph[nCharSlot]];
++            if (gi.mnGlyphIndex == GF_DROPPED)
++            {
++                continue;
++            }
++            int nCluster = mvChar2BaseGlyph[nCharSlot];
++            long origClusterWidth = gi.mnNewWidth;
++            long nMin = gi.maLinearPos.X();
++            long nMax = gi.maLinearPos.X() + gi.mnNewWidth;
++            // attached glyphs are always stored after their base rtl or ltr
++            while (++nCluster < static_cast<int>(mvGlyphs.size()) &&
++                !mvGlyphs[nCluster].IsClusterStart())
++            {
++                origClusterWidth += mvGlyphs[nCluster].mnNewWidth;
++                if (mvGlyph2Char[nCluster] == nCharSlot)
++                {
++                    nMin = std::min(nMin, mvGlyphs[nCluster].maLinearPos.X());
++                    nMax = std::min(nMax, mvGlyphs[nCluster].maLinearPos.X() + mvGlyphs[nCluster].mnNewWidth);
++                }
++            }
++            if (bRtl)
++            {
++                pCaretXArray[i+1] = nMin;
++                pCaretXArray[i] = nMax;
++            }
++            else
++            {
++                pCaretXArray[i] = nMin;
++                pCaretXArray[i+1] = nMax;
++            }
++            prevBase = mvChar2BaseGlyph[nCharSlot];
++            prevClusterWidth = origClusterWidth;
++        }
++        else if (prevBase > -1)
++        {
++            // this could probably be improved
++            assert((prevBase > -1) && (prevBase < (signed)mvGlyphs.size()));
++            GlyphItem gi = mvGlyphs[prevBase];
++            int nGlyph = prevBase + 1;
++            // try to find a better match, otherwise default to complete cluster
++            for (; nGlyph < static_cast<int>(mvGlyphs.size()) &&
++                 !mvGlyphs[nGlyph].IsClusterStart(); nGlyph++)
++            {
++                if (mvGlyph2Char[nGlyph] == nCharSlot)
++                {
++                    gi = mvGlyphs[nGlyph];
++                    break;
++                }
++            }
++            long nGWidth = gi.mnNewWidth;
++            // if no match position at end of cluster
++            if (nGlyph == static_cast<int>(mvGlyphs.size()) ||
++                mvGlyphs[nGlyph].IsClusterStart())
++            {
++                nGWidth = prevClusterWidth;
++                if (bRtl)
++                {
++                    pCaretXArray[i+1] = gi.maLinearPos.X();
++                    pCaretXArray[i] = gi.maLinearPos.X();
++                }
++                else
++                {
++                    pCaretXArray[i] = gi.maLinearPos.X() + prevClusterWidth;
++                    pCaretXArray[i+1] = gi.maLinearPos.X() + prevClusterWidth;
++                }
++            }
++            else
++            {
++                if (bRtl)
++                {
++                    pCaretXArray[i+1] = gi.maLinearPos.X();
++                    pCaretXArray[i] = gi.maLinearPos.X() + gi.mnNewWidth;
++                }
++                else
++                {
++                    pCaretXArray[i] = gi.maLinearPos.X();
++                    pCaretXArray[i+1] = gi.maLinearPos.X() + gi.mnNewWidth;
++                }
++            }
++        }
++        else
++        {
++            pCaretXArray[i] = pCaretXArray[i+1] = 0;
++        }
++#ifdef GRLAYOUT_DEBUG
++        fprintf(grLog(),"%d,%ld-%ld\t", nCharSlot, pCaretXArray[i], pCaretXArray[i+1]);
++#endif
++    }
++#ifdef GRLAYOUT_DEBUG
++    fprintf(grLog(),"\n");
++#endif
++}
++
++
++// GetNextGlyphs returns a contiguous sequence of glyphs that can be
++// rendered together. It should never return a dropped glyph.
++// The glyph_slot returned should be the index of the next visible
++// glyph after the last glyph returned by this call.
++// The char_index array should be filled with the characters corresponding
++// to each glyph returned.
++// glyph_adv array should be a virtual width such that if successive
++// glyphs returned by this method are added one after the other they
++// have the correct spacing.
++// The logic in this method must match that expected in MultiSalLayout which
++// is used when glyph fallback is in operation.
++int GraphiteLayout::GetNextGlyphs( int length, sal_GlyphId * glyph_out,
++        ::Point & aPosOut, int &glyph_slot, sal_Int32 * glyph_adv, int *char_index) const
++{
++  // Sanity check on the slot index.
++  if (glyph_slot >= signed(mvGlyphs.size()))
++  {
++    glyph_slot = mvGlyphs.size();
++    return 0;
++  }
++  assert(glyph_slot >= 0);
++  // Find the first glyph in the substring.
++  for (; glyph_slot < signed(mvGlyphs.size()) &&
++          ((mvGlyphs.begin() + glyph_slot)->mnGlyphIndex == GF_DROPPED);
++          ++glyph_slot) {};
++
++  // Update the length
++  const int nGlyphSlotEnd = std::min(size_t(glyph_slot + length), mvGlyphs.size());
++
++  // We're all out of glyphs here.
++  if (glyph_slot == nGlyphSlotEnd)
++  {
++    return 0;
++  }
++
++  // Find as many glyphs as we can which can be drawn in one go.
++  Glyphs::const_iterator glyph_itr = mvGlyphs.begin() + glyph_slot;
++  const int         glyph_slot_begin = glyph_slot;
++  const int            initial_y_pos = glyph_itr->maLinearPos.Y();
++
++  // Set the position to the position of the start glyph.
++  ::Point aStartPos = glyph_itr->maLinearPos;
++  //aPosOut = glyph_itr->maLinearPos;
++  aPosOut = GetDrawPosition(aStartPos);
++
++
++  for (;;)  // Forever
++  {
++     // last index of the range from glyph_to_chars does not include this glyph
++     if (char_index)
++     {
++        assert((glyph_slot >= -1) && (glyph_slot < (signed)mvGlyph2Char.size()));
++        if (mvGlyph2Char[glyph_slot] == -1)
++            *char_index++ = mvCharDxs.size();
++        else
++            *char_index++ = mvGlyph2Char[glyph_slot];
++     }
++     // Copy out this glyphs data.
++     ++glyph_slot;
++     *glyph_out++ = glyph_itr->mnGlyphIndex;
++
++     // Find the actual advance - this must be correct if called from
++     // MultiSalLayout::AdjustLayout which requests one glyph at a time.
++     const long nGlyphAdvance = (glyph_slot == static_cast<int>(mvGlyphs.size()))?
++          glyph_itr->mnNewWidth :
++          ((glyph_itr+1)->maLinearPos.X() - glyph_itr->maLinearPos.X());
++
++#ifdef GRLAYOUT_DEBUG
++    fprintf(grLog(),"GetNextGlyphs g%d c%d x%ld,%ld adv%ld, pos %ld,%ld\n", glyph_slot - 1,
++            mvGlyph2Char[glyph_slot-1], glyph_itr->maLinearPos.X(), glyph_itr->maLinearPos.Y(), nGlyphAdvance,
++            aPosOut.X(), aPosOut.Y());
++#endif
++
++     if (glyph_adv)  // If we are returning advance store it.
++       *glyph_adv++ = nGlyphAdvance;
++     else // Stop when next advance is unexpected.
++       if (glyph_itr->mnOrigWidth != nGlyphAdvance)  break;
++
++     // Have fetched all the glyphs we need to
++     if (glyph_slot == nGlyphSlotEnd)
++         break;
++
++     ++glyph_itr;
++     // Stop when next y position is unexpected.
++     if (initial_y_pos != glyph_itr->maLinearPos.Y())
++       break;
++
++     // Stop if glyph dropped
++     if (glyph_itr->mnGlyphIndex == GF_DROPPED)
++       break;
++  }
++  int numGlyphs = glyph_slot - glyph_slot_begin;
++  // move the next glyph_slot to a glyph that hasn't been dropped
++  while (glyph_slot < static_cast<int>(mvGlyphs.size()) &&
++         (mvGlyphs.begin() + glyph_slot)->mnGlyphIndex == GF_DROPPED)
++         ++glyph_slot;
++  return numGlyphs;
++}
++
++
++void GraphiteLayout::MoveGlyph( int nGlyphIndex, long nNewPos )
++{
++    // TODO it might be better to actualy implement simplify properly, but this
++    // needs to be done carefully so the glyph/char maps are maintained
++    // If a glyph has been dropped then it wasn't returned by GetNextGlyphs, so
++    // the index here may be wrong
++    while ((mvGlyphs[nGlyphIndex].mnGlyphIndex == GF_DROPPED) &&
++           (nGlyphIndex < (signed)mvGlyphs.size()))
++    {
++        nGlyphIndex++;
++    }
++    const long dx = nNewPos - mvGlyphs[nGlyphIndex].maLinearPos.X();
++
++    if (dx == 0)  return;
++    // GenericSalLayout only changes maLinearPos, mvCharDxs doesn't change
++#ifdef GRLAYOUT_DEBUG
++    fprintf(grLog(),"Move %d (%ld,%ld) c%d by %ld\n", nGlyphIndex, mvGlyphs[nGlyphIndex].maLinearPos.X(), nNewPos, mvGlyph2Char[nGlyphIndex], dx);
++#endif
++    for (size_t gi = nGlyphIndex; gi < mvGlyphs.size(); gi++)
++    {
++        mvGlyphs[gi].maLinearPos.X() += dx;
++    }
++    // width does need to be updated for correct fallback
++    mnWidth += dx;
++}
++
++
++void GraphiteLayout::DropGlyph( int nGlyphIndex )
++{
++    if(nGlyphIndex >= signed(mvGlyphs.size()))
++        return;
++
++    GlyphItem & glyph = mvGlyphs[nGlyphIndex];
++    glyph.mnGlyphIndex = GF_DROPPED;
++#ifdef GRLAYOUT_DEBUG
++    fprintf(grLog(),"Dropped %d\n", nGlyphIndex);
++#endif
++}
++
++void GraphiteLayout::Simplify( bool isBaseLayout )
++{
++  const sal_GlyphId dropMarker = isBaseLayout ? GF_DROPPED : 0;
++
++  Glyphs::iterator gi = mvGlyphs.begin();
++  // TODO check whether we need to adjust positions here
++  // MultiSalLayout seems to move the glyphs itself, so it may not be needed.
++  long deltaX = 0;
++  while (gi != mvGlyphs.end())
++  {
++      if (gi->mnGlyphIndex == dropMarker)
++      {
++        deltaX += gi->mnNewWidth;
++        gi->mnNewWidth = 0;
++      }
++      else
++      {
++        deltaX = 0;
++      }
++      //mvCharDxs[mvGlyph2Char[gi->mnCharPos]] -= deltaX;
++      ++gi;
++  }
++#ifdef GRLAYOUT_DEBUG
++  fprintf(grLog(),"Simplify base%d dx=%ld newW=%ld\n", isBaseLayout, deltaX, mnWidth - deltaX);
++#endif
++  // discard width from trailing dropped glyphs, but not those in the middle
++  mnWidth -= deltaX;
++}
+Index: vcl/source/glyphs/graphite_serverfont.cxx
+===================================================================
+--- vcl/source/glyphs/graphite_serverfont.cxx	(.../tags/DEV300_m49)	(Revision 0)
++++ vcl/source/glyphs/graphite_serverfont.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,69 @@
++//
++// C++ Implementation: GraphiteLayout
++//
++// Description: An implementation of the SalLayout interface that use the
++//              Graphite engine.
++//
++// Author: Tim Eves <tim_eves at sil.org>
++//
++// Copyright: Copyright (C) 2003 SIL International.
++//            All rights reserved. Distributable under the terms of either
++//            the Common Public License or the GNU Lesser General Public
++//            License.
++//
++
++// We need this to enable namespace support in libgrengine headers.
++#define GR_NAMESPACE
++
++// Header files
++//
++
++// Platform
++#include <vcl/sallayout.hxx>
++// Module
++#include "gcach_ftyp.hxx"
++#include <vcl/graphite_features.hxx>
++#include "graphite_textsrc.hxx"
++#include <vcl/graphite_serverfont.hxx>
++
++#ifndef MSC
++
++//
++// An implementation of the GraphiteLayout interface to enable Graphite enabled fonts to be used.
++//
++
++GraphiteServerFontLayout::GraphiteServerFontLayout(GraphiteFontAdaptor * pFont) throw()
++  : ServerFontLayout(pFont->font()), mpFont(pFont),
++    maImpl(*mpFont, mpFont->features(), pFont)
++{
++    // Nothing needed here
++}
++
++GraphiteServerFontLayout::~GraphiteServerFontLayout() throw()
++{
++    delete mpFont;
++    mpFont = NULL;
++}
++
++const sal_Unicode* GraphiteServerFontLayout::getTextPtr() const
++{
++    return maImpl.textSrc()->getLayoutArgs().mpStr +
++        maImpl.textSrc()->getLayoutArgs().mnMinCharPos;
++}
++
++sal_GlyphId GraphiteLayoutImpl::getKashidaGlyph(int & width)
++{
++    int nKashidaIndex = mpFont->font().GetGlyphIndex( 0x0640 );
++    if( nKashidaIndex != 0 )
++    {
++        const GlyphMetric& rGM = mpFont->font().GetGlyphMetric( nKashidaIndex );
++        width = rGM.GetCharWidth();
++    }
++    else
++    {
++        width = 0;
++    }
++    return nKashidaIndex;
++}
++
++#endif
+Index: vcl/source/glyphs/graphite_features.cxx
+===================================================================
+--- vcl/source/glyphs/graphite_features.cxx	(.../tags/DEV300_m49)	(Revision 0)
++++ vcl/source/glyphs/graphite_features.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,268 @@
++/*-----------------------------------------------------------------------------
++Copyright (C) 2008 www.thanlwinsoft.org
++
++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:
++Responsibility: Keith Stribley
++Last reviewed: Not yet.
++
++Description:
++Parse a string of features specified as ; separated pairs.
++e.g.
++1001=1;2002=2;fav1=0
++
++-----------------------------------------------------------------------------*/
++
++#include <sal/types.h>
++
++#ifdef MSC
++#include <tools/svwin.h>
++#include <svsys.h>
++#endif
++
++#include <vcl/graphite_features.hxx>
++
++using namespace grutils;
++// These mustn't conflict with font name lists which use ; and ,
++const char GrFeatureParser::FEAT_PREFIX = ':';
++const char GrFeatureParser::FEAT_SEPARATOR = '&';
++const char GrFeatureParser::FEAT_ID_VALUE_SEPARATOR = '=';
++const std::string GrFeatureParser::ISO_LANG("lang");
++
++GrFeatureParser::GrFeatureParser(gr::Font & font, const std::string lang)
++    : mnNumSettings(0), mbErrors(false)
++{
++    maLang.rgch[0] = maLang.rgch[1] = maLang.rgch[2] = maLang.rgch[3] = '\0';
++    setLang(font, lang);
++}
++
++GrFeatureParser::GrFeatureParser(gr::Font & font, const std::string features, const std::string lang)
++    : mnNumSettings(0), mbErrors(false)
++{
++    size_t nEquals = 0;
++    size_t nFeatEnd = 0;
++    size_t pos = 0;
++    maLang.rgch[0] = maLang.rgch[1] = maLang.rgch[2] = maLang.rgch[3] = '\0';
++    setLang(font, lang);
++    while (pos < features.length() && mnNumSettings < MAX_FEATURES)
++    {
++        nEquals = features.find(FEAT_ID_VALUE_SEPARATOR,pos);
++        if (nEquals == std::string::npos)
++        {
++            mbErrors = true;
++            break;
++        }
++        // check for a lang=xxx specification
++        if (features.compare(pos, nEquals - pos, ISO_LANG) == 0)
++        {
++            pos = nEquals + 1;
++            nFeatEnd = features.find(FEAT_SEPARATOR, pos);
++            if (nFeatEnd == std::string::npos)
++            {
++                nFeatEnd = features.length();
++            }
++            if (nFeatEnd - pos > 3)
++                mbErrors = true;
++            else
++            {
++                gr::isocode aLang = maLang;
++                for (size_t i = pos; i < nFeatEnd; i++)
++                    aLang.rgch[i-pos] = features[i];
++                std::pair<gr::LanguageIterator,gr::LanguageIterator> aSupported
++                    = font.getSupportedLanguages();
++                gr::LanguageIterator iL = aSupported.first;
++                while (iL != aSupported.second)
++                {
++                    gr::isocode aSupportedLang = *iL;
++                    // here we only expect full 3 letter codes
++                    if (aLang.rgch[0] == aSupportedLang.rgch[0] &&
++                        aLang.rgch[1] == aSupportedLang.rgch[1] &&
++                        aLang.rgch[2] == aSupportedLang.rgch[2] &&
++                        aLang.rgch[3] == aSupportedLang.rgch[3]) break;
++                    ++iL;
++                }
++                if (iL == aSupported.second) mbErrors = true;
++                else maLang = aLang;
++            }
++        }
++        else
++        {
++            if (isCharId(features, pos, nEquals - pos))
++                maSettings[mnNumSettings].id = getCharId(features, pos, nEquals - pos);
++            else maSettings[mnNumSettings].id = getIntValue(features, pos, nEquals - pos);
++            pos = nEquals + 1;
++            nFeatEnd = features.find(FEAT_SEPARATOR, pos);
++            if (nFeatEnd == std::string::npos)
++            {
++                nFeatEnd = features.length();
++            }
++            if (isCharId(features, pos, nFeatEnd - pos))
++                maSettings[mnNumSettings].value = getCharId(features, pos, nFeatEnd - pos);
++            else
++                maSettings[mnNumSettings].value= getIntValue(features, pos, nFeatEnd - pos);
++            if (isValid(font, maSettings[mnNumSettings]))
++                mnNumSettings++;
++            else
++                mbErrors = true;
++        }
++        pos = nFeatEnd + 1;
++    }
++}
++
++void GrFeatureParser::setLang(gr::Font & font, const std::string & lang)
++{
++    gr::isocode aLang = {{0,0,0,0}};
++    if (lang.length() > 2)
++    {
++        for (size_t i = 0; i < lang.length() && i < 3; i++)
++        {
++            if (lang[i] == '-') break;
++            aLang.rgch[i] = lang[i];
++        }
++        std::pair<gr::LanguageIterator,gr::LanguageIterator> aSupported
++                    = font.getSupportedLanguages();
++        gr::LanguageIterator iL = aSupported.first;
++        while (iL != aSupported.second)
++        {
++            gr::isocode aSupportedLang = *iL;
++            if (aLang.rgch[0] == aSupportedLang.rgch[0] &&
++                aLang.rgch[1] == aSupportedLang.rgch[1] &&
++                aLang.rgch[2] == aSupportedLang.rgch[2] &&
++                aLang.rgch[3] == aSupportedLang.rgch[3]) break;
++            ++iL;
++        }
++        if (iL != aSupported.second)
++            maLang = aLang;
++#ifdef DEBUG
++        else
++            printf("%s has no features\n", aLang.rgch);
++#endif
++    }
++}
++
++GrFeatureParser::GrFeatureParser(const GrFeatureParser & aCopy)
++ : maLang(aCopy.maLang), mbErrors(aCopy.mbErrors)
++{
++    mnNumSettings = aCopy.getFontFeatures(maSettings);
++}
++
++GrFeatureParser::~GrFeatureParser()
++{
++}
++
++size_t GrFeatureParser::getFontFeatures(gr::FeatureSetting settings[64]) const
++{
++    if (settings)
++    {
++        std::copy(maSettings, maSettings + mnNumSettings, settings);
++    }
++    return mnNumSettings;
++}
++
++bool GrFeatureParser::isValid(gr::Font & font, gr::FeatureSetting & setting)
++{
++    gr::FeatureIterator i = font.featureWithID(setting.id);
++    if (font.getFeatures().second == i)
++    {
++        return false;
++    }
++    std::pair< gr::FeatureSettingIterator, gr::FeatureSettingIterator >
++        validValues = font.getFeatureSettings(i);
++    gr::FeatureSettingIterator j = validValues.first;
++    while (j != validValues.second)
++    {
++        if (*j == setting.value) return true;
++        ++j;
++    }
++    return false;
++}
++
++bool GrFeatureParser::isCharId(const std::string & id, size_t offset, size_t length)
++{
++    if (length > 4) return false;
++    for (size_t i = 0; i < length; i++)
++    {
++        if (i > 0 && id[offset+i] == '\0') continue;
++        if ((id[offset+i]) < 0x20 || (id[offset+i]) < 0)
++            return false;
++        if (i==0 && id[offset+i] < 0x41)
++            return false;
++    }
++    return true;
++}
++
++int GrFeatureParser::getCharId(const std::string & id, size_t offset, size_t length)
++{
++    FeatId charId;
++    charId.num = 0;
++#ifdef WORDS_BIGENDIAN
++    for (size_t i = 0; i < length; i++)
++    {
++        charId.label[i] = id[offset+i];
++    }
++#else
++    for (size_t i = 0; i < length; i++)
++    {
++        charId.label[3-i] = id[offset+i];
++    }
++#endif
++    return charId.num;
++}
++
++int GrFeatureParser::getIntValue(const std::string & id, size_t offset, size_t length)
++{
++    int value = 0;
++    int sign = 1;
++    for (size_t i = 0; i < length; i++)
++    {
++        switch (id[offset + i])
++        {
++        case '0':
++        case '1':
++        case '2':
++        case '3':
++        case '4':
++        case '5':
++        case '6':
++        case '7':
++        case '8':
++        case '9':
++            value *= 10;
++            if (sign < 0)
++            {
++                value = -(id[offset + i] - '0');
++                sign = 1;
++            }
++            value += (id[offset + i] - '0');
++            break;
++        case '-':
++            if (i == 0)
++                sign = -1;
++            else
++            {
++                mbErrors = true;
++                break;
++            }
++        default:
++            mbErrors = true;
++            break;
++        }
++    }
++    return value;
++}
++
++
++sal_Int32 GrFeatureParser::hashCode() const
++{
++    union IsoHash { sal_Int32 mInt; gr::isocode mCode; };
++    IsoHash isoHash;
++    isoHash.mCode = maLang;
++    sal_Int32 hash = isoHash.mInt;
++    for (size_t i = 0; i < mnNumSettings; i++)
++    {
++        hash = (hash << 16) ^ ((maSettings[i].id << 8) | maSettings[i].value);
++    }
++    return hash;
++}
+
+Eigenschaftsänderungen: vcl/source/glyphs/gcach_layout.cxx
+___________________________________________________________________
+Gelöscht: svn:executable
+   - *
+
+Index: vcl/source/glyphs/makefile.mk
+===================================================================
+--- vcl/source/glyphs/makefile.mk	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/source/glyphs/makefile.mk	(.../cws/graphite01)	(Revision 273505)
+@@ -54,8 +54,29 @@
+ 		$(SLO)$/gcach_rbmp.obj		\
+ 		$(SLO)$/gcach_layout.obj	\
+ 		$(SLO)$/gcach_ftyp.obj
++
++.IF "$(ENABLE_GRAPHITE)" != ""
++CFLAGS+=-DENABLE_GRAPHITE
++SLOFILES+=	$(SLO)$/graphite_adaptors.obj	\
++		$(SLO)$/graphite_features.obj	\
++		$(SLO)$/graphite_cache.obj	\
++		$(SLO)$/graphite_textsrc.obj	\
++		$(SLO)$/graphite_serverfont.obj	\
++		$(SLO)$/graphite_layout.obj
+ .ENDIF
+ 
++.ELSE
++.IF "$(ENABLE_GRAPHITE)" == "TRUE"
++# make use of stlport headerfiles
++EXT_USE_STLPORT=TRUE
++SLOFILES=\
++		$(SLO)$/graphite_textsrc.obj	\
++		$(SLO)$/graphite_cache.obj	\
++		$(SLO)$/graphite_features.obj	\
++		$(SLO)$/graphite_layout.obj
++.ENDIF
++.ENDIF
++
+ # --- Targets ------------------------------------------------------
+ 
+ .INCLUDE :  target.mk
+Index: vcl/source/glyphs/graphite_textsrc.hxx
+===================================================================
+--- vcl/source/glyphs/graphite_textsrc.hxx	(.../tags/DEV300_m49)	(Revision 0)
++++ vcl/source/glyphs/graphite_textsrc.hxx	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,112 @@
++#ifndef _SV_GRAPHITETEXTSRC_HXX
++#define _SV_GRAPHITETEXTSRC_HXX
++//
++// C++ Interface: Graphite to SAL adaptor classes
++//
++// Description: Implements the Graphite interfaces IGrTextSource and
++//              IGrGraphics which provide Graphite with access to the
++//              app's text storage system and the platform's font and
++//              graphics systems.
++//
++// Author: Tim Eves <tim_eves at sil.org>
++//
++// Copyright: Copyright (C) 2003-2004 SIL International.
++//            All rights reserved. Distributable under the terms of either
++//            the Common Public License or the GNU Lesser General Public
++//            License.
++//
++
++// We need this to enable namespace support in libgrengine headers.
++#define GR_NAMESPACE
++
++// Standard Library
++#include <stdexcept>
++// Platform
++
++#ifndef _SVWIN_H
++#include <tools/svwin.h>
++#endif
++
++#ifndef _SV_SVSYS_HXX
++#include <svsys.h>
++#endif
++
++#ifndef _SV_SALGDI_HXX
++#include <vcl/salgdi.hxx>
++#endif
++
++#ifndef _SV_SALLAYOUT_HXX
++#include <vcl/sallayout.hxx>
++#endif
++
++// Module
++#include "vcl/dllapi.h"
++
++// Libraries
++#include <graphite/GrClient.h>
++#include <graphite/Font.h>
++#include <graphite/ITextSource.h>
++
++// Module type definitions and forward declarations.
++//
++namespace grutils
++{
++    class GrFeatureParser;
++}
++// Implements the Adaptor pattern to adapt the LayoutArgs and the ServerFont interfaces to the
++// gr::IGrTextSource interface.
++// @author tse
++//
++class TextSourceAdaptor : public gr::ITextSource
++{
++public:
++        TextSourceAdaptor(ImplLayoutArgs &layout_args, const int nContextLen) throw();
++        ~TextSourceAdaptor();
++        virtual gr::UtfType     utfEncodingForm();
++        virtual size_t          getLength();
++        virtual size_t          fetch(gr::toffset ichMin, size_t cch, gr::utf32 * prgchBuffer);
++        virtual size_t          fetch(gr::toffset ichMin, size_t cch, gr::utf16 * prgchwBuffer);
++        virtual size_t          fetch(gr::toffset ichMin, size_t cch, gr::utf8  * prgchsBuffer);
++        virtual bool            getRightToLeft(gr::toffset ich);
++        virtual unsigned int    getDirectionDepth(gr::toffset ich);
++        virtual float           getVerticalOffset(gr::toffset ich);
++        virtual gr::isocode     getLanguage(gr::toffset ich);
++
++        virtual std::pair<gr::toffset, gr::toffset> propertyRange(gr::toffset ich);
++        virtual size_t  getFontFeatures(gr::toffset ich, gr::FeatureSetting * prgfset);
++        virtual bool    sameSegment(gr::toffset ich1, gr::toffset ich2);
++
++        operator ImplLayoutArgs & () throw();
++        void setFeatures(const grutils::GrFeatureParser * pFeatures);
++        const ImplLayoutArgs & getLayoutArgs() const { return maLayoutArgs; }
++        size_t          getContextLength() const { return mnEnd; };
++        inline void switchLayoutArgs(ImplLayoutArgs & newArgs);
++private:
++        // Prevent the generation of a default assignment operator.
++        TextSourceAdaptor & operator=(const TextSourceAdaptor &);
++
++        void getCharProperties(const int, int &, int &, size_t &);
++
++        ImplLayoutArgs  maLayoutArgs;
++        size_t    mnEnd;
++        const grutils::GrFeatureParser * mpFeatures;
++};
++
++inline TextSourceAdaptor::TextSourceAdaptor(ImplLayoutArgs &la, const int nContextLen) throw()
++  : maLayoutArgs(la),
++    mnEnd(std::min(la.mnLength, nContextLen)),
++    mpFeatures(NULL)
++{
++}
++
++inline  TextSourceAdaptor::operator ImplLayoutArgs & () throw() {
++        return maLayoutArgs;
++}
++
++inline void TextSourceAdaptor::switchLayoutArgs(ImplLayoutArgs & aNewArgs)
++{
++    mnEnd += aNewArgs.mnMinCharPos - maLayoutArgs.mnMinCharPos;
++    maLayoutArgs = aNewArgs;
++}
++
++#endif
+
+Eigenschaftsänderungen: vcl/source/glyphs/gcach_rbmp.cxx
+___________________________________________________________________
+Gelöscht: svn:executable
+   - *
+
+Index: vcl/source/glyphs/graphite_cache.cxx
+===================================================================
+--- vcl/source/glyphs/graphite_cache.cxx	(.../tags/DEV300_m49)	(Revision 0)
++++ vcl/source/glyphs/graphite_cache.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,198 @@
++/*************************************************************************
++ *
++ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
++ *
++ * Copyright 2008 by Sun Microsystems, Inc.
++ *
++ * OpenOffice.org - a multi-platform office productivity suite
++ *
++ * $RCSfile: graphite_cache.cxx,v $
++ * $Revision: 1.1.2.1 $
++ *
++ * This file is part of OpenOffice.org.
++ *
++ * OpenOffice.org is free software: you can redistribute it and/or modify
++ * it under the terms of the GNU Lesser General Public License version 3
++ * only, as published by the Free Software Foundation.
++ *
++ * OpenOffice.org is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU Lesser General Public License version 3 for more details
++ * (a copy is included in the LICENSE file that accompanied this code).
++ *
++ * You should have received a copy of the GNU Lesser General Public License
++ * version 3 along with OpenOffice.org.  If not, see
++ * <http://www.openoffice.org/license.html>
++ * for a copy of the LGPLv3 License.
++ *
++ ************************************************************************/
++
++#ifdef MSC
++#include <tools/svwin.h>
++#include <svsys.h>
++#endif
++
++#include <tools/debug.hxx>
++#include <vcl/sallayout.hxx>
++
++#include <graphite/GrClient.h>
++#include <graphite/Segment.h>
++
++#include <rtl/ustring.hxx>
++#include <vcl/graphite_layout.hxx>
++#include <vcl/graphite_cache.hxx>
++
++#include "graphite_textsrc.hxx"
++
++GrSegRecord::GrSegRecord(rtl::OUString * rope, TextSourceAdaptor * textSrc, gr::Segment * seg, bool bIsRtl)
++    : m_rope(rope), m_text(textSrc), m_seg(seg), m_nextKey(NULL),
++    m_fontScale(0.0f), mbIsRtl(bIsRtl), m_lockCount(0)
++{
++	m_pStr = textSrc->getLayoutArgs().mpStr + seg->startCharacter();
++	m_startChar = seg->startCharacter();
++}
++
++GrSegRecord::~GrSegRecord()
++{
++	clear();
++}
++
++void GrSegRecord::reuse(rtl::OUString * rope, TextSourceAdaptor * textSrc, gr::Segment * seg, bool bIsRtl)
++{
++    clear();
++    mnWidth = 0;
++    m_rope = rope;
++    m_text = textSrc;
++    m_seg = seg;
++    m_nextKey = NULL;
++    m_pStr = textSrc->getLayoutArgs().mpStr + seg->startCharacter();
++    m_startChar = seg->startCharacter();
++    mbIsRtl = bIsRtl;
++}
++
++void GrSegRecord::clearVectors()
++{
++    mvGlyphs.clear();
++    mvCharDxs.clear();
++    mvChar2BaseGlyph.clear();
++    mvGlyph2Char.clear();
++}
++
++void GrSegRecord::clear()
++{
++#ifdef GR_DEBUG_TEXT
++    if (m_lockCount != 0)
++      OutputDebugString("GrSegRecord locked!");
++#endif
++    clearVectors();
++    delete m_rope;
++    delete m_seg;
++    delete m_text;
++    m_rope = NULL;
++    m_seg = NULL;
++    m_text = NULL;
++    m_fontScale = 0.0f;
++    m_lockCount = 0;
++}
++
++GrSegRecord * GraphiteSegmentCache::cacheSegment(TextSourceAdaptor * adapter, gr::Segment * seg, bool bIsRtl)
++{
++    GrSegRecord * record = NULL;
++    // We keep a record of the oldest key and the last key added
++    // when the next key is added, the record for the prevKey's m_nextKey field
++    // is updated to the newest key so that m_oldestKey can be updated to the
++    // next oldest key when the record for m_oldestKey is deleted
++    if (m_segMap.size() > SEG_CACHE_SIZE)
++    {
++      GraphiteSegMap::iterator oldestPair = m_segMap.find(reinterpret_cast<long>(m_oldestKey));
++      // oldest record may no longer exist if a buffer was changed
++      if (oldestPair != m_segMap.end())
++      {
++        record = oldestPair->second;
++        m_segMap.erase(reinterpret_cast<long>(m_oldestKey));
++        GrRMEntry range = m_ropeMap.equal_range((*(record->m_rope)).hashCode());
++        while (range.first != range.second)
++        {
++          if (range.first->second == record)
++          {
++            m_ropeMap.erase(range.first);
++            break;
++          }
++          ++range.first;
++        }
++        m_oldestKey = record->m_nextKey;
++        // record will be reused, so don't delete
++      }
++	}
++
++
++//    const int seg_char_limit = min(adapter->maLayoutArgs().mnLength,
++//      adapter->maLayoutArgs().mnEndCharPos
++//      + GraphiteLayout::EXTRA_CONTEXT_LENGTH);
++//    if (seg->stopCharacter() - seg->startCharacter() <= 0)
++//      OutputDebugString("Invalid seg indices\n");
++    rtl::OUString * pRope = new rtl::OUString(adapter->getLayoutArgs().mpStr + seg->startCharacter(),
++       seg->stopCharacter() - seg->startCharacter());
++    if (!pRope) return NULL;
++    bool reuse = false;
++    if (record)
++      record->reuse(pRope, adapter, seg, bIsRtl);
++    else
++      record = new GrSegRecord(pRope, adapter, seg, bIsRtl);
++    if (!record)
++    {
++      delete pRope;
++      return NULL;
++    }
++    GraphiteSegMap::iterator iMap =
++      m_segMap.find(reinterpret_cast<long>(record->m_pStr));
++    if (iMap != m_segMap.end())
++    {
++      // the buffer has changed, so the old cached Segment is useless
++      reuse = true;
++      GrSegRecord * found = iMap->second;
++      // Note: we reuse the old next key to avoid breaking our history
++      // chain. This means it will be prematurely deleted, but this is
++      // unlikely to happen very often.
++      record->m_nextKey = found->m_nextKey;
++      // overwrite the old record
++      m_segMap[reinterpret_cast<long>(record->m_pStr)] = record;
++      // erase the old rope key and save the new one
++      GrRMEntry range = m_ropeMap.equal_range((*(found->m_rope)).hashCode());
++      while (range.first != range.second)
++      {
++        if (range.first->second == found)
++        {
++          m_ropeMap.erase(range.first);
++          break;
++        }
++        ++range.first;
++      }
++      GraphiteRopeMap::value_type mapEntry(record->m_rope->hashCode(), record);
++      m_ropeMap.insert(mapEntry);
++      // remove the old record
++      delete found;
++      record->m_lockCount++;
++      return record;
++    }
++    m_segMap[reinterpret_cast<long>(record->m_pStr)] = record;
++    GraphiteRopeMap::value_type mapEntry((*(record->m_rope)).hashCode(), record);
++    m_ropeMap.insert(mapEntry);
++
++    if (m_oldestKey == NULL)
++    {
++      m_oldestKey = record->m_pStr;
++      m_prevKey = record->m_pStr;
++    }
++    else if (reuse == false)
++    {
++      DBG_ASSERT(m_segMap.count(reinterpret_cast<long>(m_prevKey)),
++        "Previous key got lost somehow!");
++      m_segMap.find(reinterpret_cast<long>(m_prevKey))
++        ->second->m_nextKey = record->m_pStr;
++      m_prevKey = record->m_pStr;
++    }
++    record->m_lockCount++;
++    return record;
++}
+Index: vcl/source/glyphs/gcach_ftyp.cxx
+===================================================================
+--- vcl/source/glyphs/gcach_ftyp.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/source/glyphs/gcach_ftyp.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -1425,6 +1425,20 @@
+         FT_Glyph_Transform( pGlyphFT, &aMatrix, NULL );
+     }
+ 
++    // Check for zero area bounding boxes as this crashes some versions of FT.
++    // This also provides a handy short cut as much of the code following
++    //  becomes an expensive nop when a glyph covers no pixels.
++    FT_BBox cbox;
++    FT_Glyph_Get_CBox(pGlyphFT, ft_glyph_bbox_unscaled, &cbox);
++  
++    if( (cbox.xMax - cbox.xMin) == 0 || (cbox.yMax - cbox.yMin == 0) )
++    {
++        nAngle = 0;
++        memset(&rRawBitmap, 0, sizeof rRawBitmap);
++        FT_Done_Glyph( pGlyphFT );
++        return true;
++    }
++    
+     if( pGlyphFT->format != FT_GLYPH_FORMAT_BITMAP )
+     {
+         if( pGlyphFT->format == FT_GLYPH_FORMAT_OUTLINE )
+Index: vcl/source/glyphs/glyphcache.cxx
+===================================================================
+--- vcl/source/glyphs/glyphcache.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/source/glyphs/glyphcache.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -41,6 +41,10 @@
+ #include <vcl/bitmap.hxx>
+ #include <vcl/outfont.hxx>
+ 
++#ifdef ENABLE_GRAPHITE
++#include <vcl/graphite_features.hxx>
++#endif
++
+ #include <rtl/ustring.hxx>		// used only for string=>hashvalue
+ #include <osl/file.hxx>
+ #include <tools/debug.hxx>
+@@ -85,12 +89,23 @@
+ {
+     // TODO: is it worth to improve this hash function?
+     sal_IntPtr nFontId = reinterpret_cast<sal_IntPtr>( rFontSelData.mpFontData );
++#ifdef ENABLE_GRAPHITE
++    if (rFontSelData.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
++        != STRING_NOTFOUND)
++    {
++        rtl::OString aFeatName = rtl::OUStringToOString( rFontSelData.maTargetName, RTL_TEXTENCODING_UTF8 );
++        nFontId ^= aFeatName.hashCode();
++    }
++#endif
+     size_t nHash = nFontId << 8;
+     nHash   += rFontSelData.mnHeight;
+     nHash   += rFontSelData.mnOrientation;
+     nHash   += rFontSelData.mbVertical;
+     nHash   += rFontSelData.meItalic;
+     nHash   += rFontSelData.meWeight;
++#ifdef ENABLE_GRAPHITE
++    nHash   += rFontSelData.meLanguage;
++#endif
+     return nHash;
+ }
+ 
+@@ -121,7 +136,16 @@
+     if( (rA.mnWidth != rB.mnWidth)
+     && ((rA.mnHeight != rB.mnWidth) || (rA.mnWidth != 0)) )
+         return false;
+-
++#ifdef ENABLE_GRAPHITE
++   if (rA.meLanguage != rB.meLanguage)
++        return false;
++   // check for features
++   if ((rA.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
++        != STRING_NOTFOUND ||
++        rB.maTargetName.Search(grutils::GrFeatureParser::FEAT_PREFIX)
++        != STRING_NOTFOUND) && rA.maTargetName != rB.maTargetName)
++        return false;
++#endif
+     return true;
+ }
+ 
+Index: vcl/inc/vcl/graphite_serverfont.hxx
+===================================================================
+--- vcl/inc/vcl/graphite_serverfont.hxx	(.../tags/DEV300_m49)	(Revision 0)
++++ vcl/inc/vcl/graphite_serverfont.hxx	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,86 @@
++#ifndef _SV_GRAPHITESERVERFONT_HXX
++#define _SV_GRAPHITESERVERFONT_HXX
++//
++// C++ Interface: GraphiteLayout
++//
++// Description: An implementation of the SalLayout interface that uses the
++//              Graphite engine.
++//
++// Author: Tim Eves <tim_eves at sil.org>
++//
++// Copyright: Copyright (C) 2003 SIL International.
++//            All rights reserved. Distributable under the terms of either
++//            the Common Public License or the GNU Lesser General Public
++//            License.
++//
++
++// We need this to enable namespace support in libgrengine headers.
++#define GR_NAMESPACE
++
++#ifndef MSC
++#include <vcl/graphite_layout.hxx>
++#include <vcl/graphite_adaptors.hxx>
++
++// Modules
++
++class VCL_DLLPUBLIC GraphiteLayoutImpl : public GraphiteLayout
++{
++public:
++    GraphiteLayoutImpl(const gr::Font & font, const grutils::GrFeatureParser * features, GraphiteFontAdaptor * pFont) throw()
++    : GraphiteLayout(font, features), mpFont(pFont) {};
++    virtual ~GraphiteLayoutImpl() throw() {};
++    virtual sal_GlyphId getKashidaGlyph(int & width);
++private:
++    GraphiteFontAdaptor * mpFont;
++};
++
++// This class implments the server font specific parts.
++// @author tse
++//
++class VCL_DLLPUBLIC GraphiteServerFontLayout : public ServerFontLayout
++{
++private:
++        mutable GraphiteFontAdaptor * mpFont;
++        // mutable so that the DrawOffset/DrawBase can be set
++        mutable GraphiteLayoutImpl maImpl;
++public:
++        GraphiteServerFontLayout(GraphiteFontAdaptor * font) throw();
++
++        virtual bool  LayoutText( ImplLayoutArgs& rArgs) { SalLayout::AdjustLayout(rArgs); return maImpl.LayoutText(rArgs); };    // first step of layout
++        virtual void  AdjustLayout( ImplLayoutArgs& rArgs)
++        {
++            SalLayout::AdjustLayout(rArgs);
++            maImpl.DrawBase() = maDrawBase;
++            maImpl.DrawOffset() = maDrawOffset;
++            maImpl.AdjustLayout(rArgs);
++        };
++        virtual long    GetTextWidth() const                           { return maImpl.GetTextWidth(); }
++        virtual long    FillDXArray( sal_Int32* dxa ) const                 { return maImpl.FillDXArray(dxa); }
++        virtual int     GetTextBreak( long mw, long ce, int f ) const  { return maImpl.GetTextBreak(mw, ce, f); }
++        virtual void    GetCaretPositions( int as, sal_Int32* cxa ) const   { maImpl.GetCaretPositions(as, cxa); }
++
++        // used by display layers
++        virtual int     GetNextGlyphs( int l, sal_GlyphId* gia, Point& p, int& s,
++                        sal_Int32* gaa = NULL, int* cpa = NULL ) const
++        {
++            maImpl.DrawBase() = maDrawBase;
++            maImpl.DrawOffset() = maDrawOffset;
++            return maImpl.GetNextGlyphs(l, gia, p, s, gaa, cpa);
++        }
++
++        virtual void    MoveGlyph( int nStart, long nNewXPos ) { maImpl.MoveGlyph(nStart, nNewXPos); };
++        virtual void    DropGlyph( int nStart ) { maImpl.DropGlyph(nStart); };
++        virtual void    Simplify( bool bIsBase ) { maImpl.Simplify(bIsBase); };
++
++        virtual ~GraphiteServerFontLayout() throw();
++
++// For use with PspGraphics
++        const sal_Unicode* getTextPtr() const;
++        int getMinCharPos() const { return mnMinCharPos; }
++        int getMaxCharPos() const { return mnEndCharPos; }
++};
++
++
++
++#endif
++#endif //_SV_GRAPHITESERVERFONT_HXX
+Index: vcl/inc/vcl/graphite_layout.hxx
+===================================================================
+--- vcl/inc/vcl/graphite_layout.hxx	(.../tags/DEV300_m49)	(Revision 0)
++++ vcl/inc/vcl/graphite_layout.hxx	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,149 @@
++#ifndef _SV_GRAPHITELAYOUT_HXX
++#define _SV_GRAPHITELAYOUT_HXX
++//
++// C++ Interface: GraphiteLayout
++//
++// Description: An implementation of the SalLayout interface that uses the
++//              Graphite engine.
++//
++// Author: Tim Eves <tim_eves at sil.org>
++//         Keith Stribley <devel at thanlwinsoft.org>
++//
++// Copyright: Copyright (C) 2003 SIL International.
++//            All rights reserved. Distributable under the terms of either
++//            the Common Public License or the GNU Lesser General Public
++//            License.
++//
++
++// We need this to enable namespace support in libgrengine headers.
++#define GR_NAMESPACE
++
++#define GRCACHE 1
++
++// Standard Library
++#include <memory>
++#include <vector>
++#include <utility>
++// Libraries
++#include <graphite/GrClient.h>
++#include <graphite/Font.h>
++#include <graphite/GrConstants.h>
++#include <graphite/GrAppData.h>
++#include <graphite/SegmentAux.h>
++// Platform
++#include <vcl/sallayout.hxx>
++#include <vcl/dllapi.h>
++// Module
++
++// For backwards compatibility with 2.4.x
++#if (SUPD == 680)
++typedef sal_Int32 sal_GlyphId;
++#endif
++
++
++// Module type definitions and forward declarations.
++//
++class TextSourceAdaptor;
++class GraphiteFontAdaptor;
++class GrSegRecord;
++// SAL/VCL types
++class ServerFont;
++// Graphite types
++namespace gr { class Segment; class GlyphIterator; }
++namespace grutils { class GrFeatureParser; }
++
++// This class uses the SIL Graphite engine to provide complex text layout services to the VCL
++// @author tse
++//
++class VCL_DLLPUBLIC GraphiteLayout : public SalLayout
++{
++public:
++    class Glyphs : public std::vector<GlyphItem>
++    {
++    public:
++        typedef std::pair<Glyphs::const_iterator, Glyphs::const_iterator> iterator_pair_t;
++
++        void    fill_from(gr::Segment & rSeg, ImplLayoutArgs & rArgs,
++            bool bRtl, long &rWidth, float fScaling,
++            std::vector<int> & rChar2Base, std::vector<int> & rGlyph2Char,
++            std::vector<int> & rCharDxs);
++        void    move_glyph(Glyphs::iterator, long dx);
++
++        const_iterator    cluster_base(const_iterator) const;
++        iterator_pair_t    neighbour_clusters(const_iterator) const;
++    private:
++        std::pair<float,float> appendCluster(gr::Segment & rSeg, ImplLayoutArgs & rArgs,
++            bool bRtl, int nFirstCharInCluster, int nNextChar,
++            int nFirstGlyphInCluster, int nNextGlyph, float fScaling,
++            std::vector<int> & rChar2Base, std::vector<int> & rGlyph2Char,
++            std::vector<int> & rCharDxs, long & rDXOffset);
++        void         append(gr::Segment & rSeg, ImplLayoutArgs & rArgs, gr::GlyphInfo & rGi, float nextGlyphOrigin, float fScaling, std::vector<int> & rChar2Base, std::vector<int> & rGlyph2Char, std::vector<int> & rCharDxs, long & rDXOffset, bool bIsBase);
++    };
++
++    mutable Glyphs          mvGlyphs;
++    void clear();
++
++private:
++    TextSourceAdaptor     * mpTextSrc; // Text source.
++    gr::LayoutEnvironment   maLayout;
++    const gr::Font         &mrFont;
++    long                    mnWidth;
++    std::vector<int>        mvCharDxs;
++    std::vector<int>        mvChar2BaseGlyph;
++    std::vector<int>        mvGlyph2Char;
++    float                   mfScaling;
++    const grutils::GrFeatureParser * mpFeatures;
++
++public:
++    GraphiteLayout(const gr::Font & font, const grutils::GrFeatureParser * features = NULL) throw();
++
++    // used by upper layers
++    virtual bool  LayoutText( ImplLayoutArgs& );    // first step of layout
++    // split into two stages to allow dc to be restored on the segment
++#ifdef GRCACHE
++    gr::Segment * CreateSegment(ImplLayoutArgs& rArgs, GrSegRecord ** pRecord = NULL);
++    bool LayoutGlyphs(ImplLayoutArgs& rArgs, gr::Segment * pSegment, GrSegRecord * pSegRecord);
++#else
++    gr::Segment * CreateSegment(ImplLayoutArgs& rArgs);
++    bool LayoutGlyphs(ImplLayoutArgs& rArgs, gr::Segment * pSegment);
++#endif
++
++    virtual void  AdjustLayout( ImplLayoutArgs& );  // adjusting positions
++
++    // methods using string indexing
++    virtual int   GetTextBreak( long nMaxWidth, long nCharExtra=0, int nFactor=1 ) const;
++    virtual long  FillDXArray( sal_Int32* pDXArray ) const;
++    virtual void  ApplyDXArray(ImplLayoutArgs &rArgs, std::vector<int> & rDeltaWidth);
++
++    virtual void  GetCaretPositions( int nArraySize, sal_Int32* pCaretXArray ) const;
++
++    // methods using glyph indexing
++    virtual int   GetNextGlyphs(int nLen, sal_GlyphId* pGlyphIdxAry, ::Point & rPos, int&,
++            sal_Int32* pGlyphAdvAry = 0, int* pCharPosAry = 0 ) const;
++
++    // used by glyph+font+script fallback
++    virtual void    MoveGlyph( int nStart, long nNewXPos );
++    virtual void    DropGlyph( int nStart );
++    virtual void    Simplify( bool bIsBase );
++
++    // Dummy implementation so layout can be shared between Linux/Windows
++    virtual void    DrawText(SalGraphics&) const {};
++
++    virtual ~GraphiteLayout() throw();
++    void SetFeatures(grutils::GrFeatureParser * aFeature) { mpFeatures = aFeature; }
++    void SetFontScale(float s) { mfScaling = s; };
++    const TextSourceAdaptor * textSrc() const { return mpTextSrc; };
++    virtual sal_GlyphId getKashidaGlyph(int & width) = 0;
++    void kashidaJustify(std::vector<int> & rDeltaWidth, sal_GlyphId, int width);
++
++    static const int EXTRA_CONTEXT_LENGTH;
++private:
++    int                   glyph_to_char(Glyphs::iterator);
++    std::pair<int,int>    glyph_to_chars(const GlyphItem &) const;
++
++    std::pair<long,long>  caret_positions(size_t) const;
++};
++
++
++
++#endif // _SV_GRAPHITELAYOUT_HXX
+Index: vcl/inc/vcl/graphite_adaptors.hxx
+===================================================================
+--- vcl/inc/vcl/graphite_adaptors.hxx	(.../tags/DEV300_m49)	(Revision 0)
++++ vcl/inc/vcl/graphite_adaptors.hxx	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,139 @@
++#ifndef _SV_GRAPHITEADAPTORS_HXX
++#define _SV_GRAPHITEADAPTORS_HXX
++//
++// C++ Interface: Graphite to SAL adaptor classes
++//
++// Description: Implements the Graphite interfaces IGrTextSource and
++//              IGrGraphics which provide Graphite with access to the
++//              app's text storage system and the platform's font and
++//              graphics systems.
++//
++// Author: Tim Eves <tim_eves at sil.org>
++//
++// Copyright: Copyright (C) 2003-2004 SIL International.
++//            All rights reserved. Distributable under the terms of either
++//            the Common Public License or the GNU Lesser General Public
++//            License.
++//
++
++// We need this to enable namespace support in libgrengine headers.
++#define GR_NAMESPACE
++
++// Standard Library
++#include <stdexcept>
++// Platform
++
++#ifndef _SVWIN_H
++#include <tools/svwin.h>
++#endif
++
++#ifndef _SV_SVSYS_HXX
++#include <svsys.h>
++#endif
++
++#ifndef _SV_SALGDI_HXX
++#include <vcl/salgdi.hxx>
++#endif
++
++#ifndef _SV_SALLAYOUT_HXX
++#include <vcl/sallayout.hxx>
++#endif
++
++// Module
++#include "vcl/dllapi.h"
++
++// Libraries
++#include <graphite/GrClient.h>
++#include <graphite/Font.h>
++#include <graphite/ITextSource.h>
++
++
++// Module type definitions and forward declarations.
++//
++#ifndef MSC
++// SAL/VCL types
++class ServerFont;
++class FreetypeServerFont;
++
++// Graphite types
++
++struct FontProperties : gr::FontProps
++{
++    FontProperties(const FreetypeServerFont & font) throw();
++};
++
++namespace grutils
++{
++    class GrFeatureParser;
++}
++
++// This class adapts the Sal font and graphics services to form required by
++// the Graphite engine.
++// @author tse
++//
++class VCL_DLLPUBLIC GraphiteFontAdaptor : public gr::Font
++{
++typedef std::map<const gr::gid16, std::pair<gr::Rect, gr::Point> > GlyphMetricMap;
++
++public:
++    static bool    IsGraphiteEnabledFont(ServerFont &) throw();
++
++    GraphiteFontAdaptor(ServerFont & font, const sal_Int32 dpi_x, const sal_Int32 dpi_y);
++    GraphiteFontAdaptor(const GraphiteFontAdaptor &) throw();
++    ~GraphiteFontAdaptor() throw();
++
++     gr::Font    * copyThis();
++
++    // Basic attribute accessors.
++    virtual float        ascent();
++    virtual float        descent();
++    virtual bool        bold();
++    virtual bool        italic();
++    virtual float        height();
++    virtual unsigned int    getDPIx();
++    virtual unsigned int    getDPIy();
++
++    // Font access methods.
++    virtual const void    * getTable(gr::fontTableId32 tableID, size_t * pcbSize);
++    virtual void          getFontMetrics(float * ascent_out, float * descent_out = 0, float * em_square_out = 0);
++
++    // Glyph metrics.
++    virtual void      getGlyphMetrics(gr::gid16 glyphID, gr::Rect & boundingBox, gr::Point & advances);
++
++    // Adaptor attributes.
++    const FontProperties    & fontProperties() const throw();
++    FreetypeServerFont        & font() const throw();
++    const grutils::GrFeatureParser * features() const { return mpFeatures; };
++
++private:
++    virtual void UniqueCacheInfo(std::wstring &, bool &, bool &);
++
++    FreetypeServerFont& mrFont;
++    FontProperties        maFontProperties;
++    const unsigned int    mnDpiX, mnDpiY;
++    const float           mfAscent,
++                    mfDescent,
++                    mfEmUnits;
++    grutils::GrFeatureParser * mpFeatures;
++    GlyphMetricMap maGlyphMetricMap;
++};
++
++// Partial implementation of class GraphiteFontAdaptor.
++//
++inline const FontProperties & GraphiteFontAdaptor::fontProperties() const throw() {
++    return maFontProperties;
++}
++
++inline FreetypeServerFont & GraphiteFontAdaptor::font() const throw() {
++    return mrFont;
++}
++#endif // not MFC
++
++// Partial implementation of class TextSourceAdaptor.
++//
++//inline const ImplLayoutArgs & TextSourceAdaptor::layoutArgs() const throw() {
++//  return _layout_args;
++//}
++
++
++#endif // _SV_GRAPHITEADAPTORS_HXX
+Index: vcl/inc/vcl/graphite_cache.hxx
+===================================================================
+--- vcl/inc/vcl/graphite_cache.hxx	(.../tags/DEV300_m49)	(Revision 0)
++++ vcl/inc/vcl/graphite_cache.hxx	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,246 @@
++//
++// C++ Implementation: GraphiteLayout
++//
++// Description: A Class to cache Graphite Segments to try to improve
++//              rendering performance.
++//
++// Author: Keith Stribley <devel at thanlwinsoft.org>
++// Contributors:
++//
++// Copyright: Copyright (C) 2006, 2008 SIL International.
++//            All rights reserved. Distributable under the terms of either
++//            the Common Public License or the GNU Lesser General Public
++//            License.
++//
++#ifndef GraphiteSegmentCache_h
++#define GraphiteSegmentCache_h
++
++#include <tools/solar.h>
++#include <rtl/ustring.h>
++
++#define GRCACHE_REUSE_VECTORS 1
++
++//#include <rope>
++#include <hash_map>
++
++class TextSourceAdaptor;
++/**
++* GrSegRecord stores a Graphite Segment and its associated text
++*/
++class GrSegRecord {
++public:
++    GrSegRecord(rtl::OUString * rope, TextSourceAdaptor * textSrc, gr::Segment * seg, bool bIsRtl);
++
++    ~GrSegRecord();
++
++    void reuse(rtl::OUString * rope, TextSourceAdaptor * textSrc, gr::Segment * seg, bool bIsRtl);
++
++    void clearVectors();
++    void clear();
++#ifdef GRCACHE_REUSE_VECTORS
++    void setGlyphVectors(long nWidth, GraphiteLayout::Glyphs & vGlyphs, std::vector<int> vCharDxs,
++                         std::vector<int> & vChar2Base, std::vector<int> & vGlyph2Char)
++    {
++        clearVectors();
++        mnWidth = nWidth;
++        mvGlyphs.insert(mvGlyphs.begin(), vGlyphs.begin(), vGlyphs.end());
++        mvCharDxs.insert(mvCharDxs.begin(),vCharDxs.begin(),vCharDxs.end());
++        mvChar2BaseGlyph.insert(mvChar2BaseGlyph.begin(),vChar2Base.begin(),vChar2Base.end());
++        mvGlyph2Char.insert(mvGlyph2Char.begin(),vGlyph2Char.begin(),vGlyph2Char.end());
++    }
++#endif
++    gr::Segment * getSegment() { return m_seg; }
++    TextSourceAdaptor * getTextSrc() { return m_text; }
++    void unlock() { --m_lockCount; }
++    bool isRtl() const { return mbIsRtl; }
++#ifdef GRCACHE_REUSE_VECTORS
++    const long & width() const { return mnWidth; }
++    const GraphiteLayout::Glyphs & glyphs() const { return mvGlyphs; }
++    const std::vector<int> & charDxs() const { return mvCharDxs; }
++    const std::vector<int> & char2BaseGlyph() const { return mvChar2BaseGlyph; }
++    const std::vector<int> & glyph2Char() const { return mvGlyph2Char; }
++#endif
++private:
++    rtl::OUString * m_rope;
++    TextSourceAdaptor * m_text;
++    gr::Segment * m_seg;
++    const xub_Unicode * m_nextKey;
++    const xub_Unicode*  m_pStr;
++    size_t m_startChar;
++    float m_fontScale;
++    long mnWidth;
++    GraphiteLayout::Glyphs mvGlyphs; // glyphs in display order
++    std::vector<int> mvCharDxs; // right hand side x offset of each glyph
++    std::vector<int> mvChar2BaseGlyph;
++    std::vector<int> mvGlyph2Char;
++    bool mbIsRtl;
++    int m_lockCount;
++    friend class GraphiteSegmentCache;
++};
++
++typedef std::hash_map<long, GrSegRecord*, std::hash<long> > GraphiteSegMap;
++typedef std::hash_multimap<size_t, GrSegRecord*> GraphiteRopeMap;
++typedef std::pair<GraphiteRopeMap::iterator, GraphiteRopeMap::iterator> GrRMEntry;
++
++/**
++* GraphiteSegmentCache contains the cached Segments for one particular font size
++*/
++class GraphiteSegmentCache
++{
++  enum {
++    // not really sure what good values are here,
++    // bucket size should be >> cache size
++    SEG_BUCKET_SIZE = 4096,
++    SEG_CACHE_SIZE = 255
++  };
++public:
++  GraphiteSegmentCache()
++    : m_segMap(SEG_BUCKET_SIZE),
++    m_oldestKey(NULL) {};
++  ~GraphiteSegmentCache()
++  {
++    m_ropeMap.clear();
++    GraphiteSegMap::iterator i = m_segMap.begin();
++    while (i != m_segMap.end())
++    {
++      GrSegRecord *r = i->second;
++      delete r;
++      ++i;
++    }
++    m_segMap.clear();
++  };
++  GrSegRecord * getSegment(ImplLayoutArgs & layoutArgs, bool bIsRtl)
++  {
++    GrSegRecord * found = NULL;
++    // try to find a segment starting at correct place, if not, try to find a
++    //  match for the complete buffer
++    GraphiteSegMap::iterator iMap =
++      m_segMap.find(reinterpret_cast<long>(layoutArgs.mpStr +
++                                           layoutArgs.mnMinCharPos));
++    if (iMap != m_segMap.end())
++    {
++      found = iMap->second;
++    }
++    else
++    {
++      iMap = m_segMap.find(reinterpret_cast<long>(layoutArgs.mpStr));
++      if (iMap != m_segMap.end())
++      {
++        found = iMap->second;
++      }
++    }
++    if (found)
++    {
++      if (found->m_seg->startCharacter() <= layoutArgs.mnMinCharPos &&
++          found->m_seg->stopCharacter() >= layoutArgs.mnEndCharPos)
++      {
++        const size_t seg_char_limit = min(layoutArgs.mnLength, layoutArgs.mnEndCharPos
++          + GraphiteLayout::EXTRA_CONTEXT_LENGTH);
++        DBG_ASSERT(found && found->m_seg, "null entry in GraphiteSegmentCache");
++        // restore original start character, in case it has changed
++        found->m_seg->setTextSourceOffset(found->m_startChar);
++        // check that characters are the same, at least in the range of
++        // interest
++        // We could use substr and ==, but substr does a copy,
++        // so its probably faster to do it like this
++        for (size_t i = layoutArgs.mnMinCharPos; i < seg_char_limit; i++)
++        {
++          //if (!found->m_rope->match(rtl::OUString(layoutArgs.mpStr[i], layoutArgs.mnLength), i - found->m_seg->startCharacter()))
++          if (found->m_rope->getStr()[i-found->m_seg->startCharacter()] != layoutArgs.mpStr[i])
++            return NULL;
++        }
++        if (found->isRtl() != bIsRtl)
++        {
++            return NULL;
++        }
++//        if (found->m_lockCount != 0)
++//          OutputDebugString("Multple users of SegRecord!");
++        found->m_lockCount++;
++      }
++      else found = NULL;
++    }
++    else
++    {
++      // the pointers aren't the same, but we might still have the same text in a segment
++      // this is expecially needed when editing a large paragraph
++      // each edit changes the pointers, but if we don't reuse any segments it gets very
++      // slow.
++      const size_t seg_char_limit = min(layoutArgs.mnLength, layoutArgs.mnEndCharPos
++          + GraphiteLayout::EXTRA_CONTEXT_LENGTH);
++      rtl::OUString * rope = new rtl::OUString(layoutArgs.mpStr + layoutArgs.mnMinCharPos,
++                                         seg_char_limit - layoutArgs.mnMinCharPos);
++      if (!rope) return NULL;
++      size_t nHash = (*(rope)).hashCode();
++      GrRMEntry range = m_ropeMap.equal_range(nHash);
++      while (range.first != range.second)
++      {
++        found = range.first->second;
++        if (found->m_lockCount == 0)
++        {
++          if(rope->match(*(found->m_rope)))
++          {
++            // found, but the pointers are all wrong
++            found->m_seg->setTextSourceOffset(layoutArgs.mnMinCharPos);
++            // the switch is done in graphite_layout.cxx
++            //found->m_text->switchLayoutArgs(layoutArgs);
++            found->m_lockCount++;
++            break;
++          }
++          else
++            found = NULL;
++        }
++        else
++          found = NULL;
++        ++(range.first);
++      }
++      delete rope;
++    }
++    return found;
++  };
++  GrSegRecord * cacheSegment(TextSourceAdaptor * adapter, gr::Segment * seg, bool bIsRtl);
++private:
++  GraphiteSegMap m_segMap;
++  GraphiteRopeMap m_ropeMap;
++  const xub_Unicode * m_oldestKey;
++  const xub_Unicode * m_prevKey;
++};
++
++typedef std::hash_map<int, GraphiteSegmentCache *, std::hash<int> > GraphiteCacheMap;
++
++/**
++* GraphiteCacheHandler maps a particular font, style, size to a GraphiteSegmentCache
++*/
++class GraphiteCacheHandler
++{
++public:
++  GraphiteCacheHandler() : m_cacheMap(255) {};
++  ~GraphiteCacheHandler()
++  {
++    GraphiteCacheMap::iterator i = m_cacheMap.begin();
++    while (i != m_cacheMap.end())
++    {
++      GraphiteSegmentCache *r = i->second;
++      delete r;
++      ++i;
++    }
++    m_cacheMap.clear();
++  };
++
++  static GraphiteCacheHandler instance;
++
++  GraphiteSegmentCache * getCache(sal_Int32 & fontHash)
++  {
++    if (m_cacheMap.count(fontHash) > 0)
++    {
++      return m_cacheMap.find(fontHash)->second;
++    }
++    GraphiteSegmentCache *pCache = new GraphiteSegmentCache();
++    m_cacheMap[fontHash] = pCache;
++    return pCache;
++  }
++private:
++  GraphiteCacheMap m_cacheMap;
++};
++
++#endif
++
+Index: vcl/inc/vcl/graphite_features.hxx
+===================================================================
+--- vcl/inc/vcl/graphite_features.hxx	(.../tags/DEV300_m49)	(Revision 0)
++++ vcl/inc/vcl/graphite_features.hxx	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,58 @@
++/*-----------------------------------------------------------------------------
++Copyright (C) 2008 www.thanlwinsoft.org
++
++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:
++Responsibility: Keith Stribley
++Last reviewed: Not yet.
++
++Description:
++Parse a string of features specified as ; separated pairs.
++e.g.
++1001=1;2002=2;fav1=0
++
++-----------------------------------------------------------------------------*/
++#include <graphite/GrClient.h>
++#include <graphite/Font.h>
++#include <graphite/GrFeature.h>
++
++namespace grutils
++{
++
++    class GrFeatureParser
++    {
++    public:
++        enum { MAX_FEATURES = 64 };
++        static const char FEAT_PREFIX;
++        static const char FEAT_SEPARATOR;
++        static const char FEAT_ID_VALUE_SEPARATOR;
++        static const std::string ISO_LANG;
++        GrFeatureParser(gr::Font & font, const std::string features, const std::string lang);
++        GrFeatureParser(gr::Font & font, const std::string lang);
++        GrFeatureParser(const GrFeatureParser & copy);
++        ~GrFeatureParser();
++        size_t getFontFeatures(gr::FeatureSetting settings[MAX_FEATURES]) const;
++        bool parseErrors() { return mbErrors; };
++        static bool isValid(gr::Font & font, gr::FeatureSetting & setting);
++        gr::isocode getLanguage() const { return maLang; };
++        bool hasLanguage() const { return (maLang.rgch[0] != '\0'); }
++        sal_Int32 hashCode() const;
++    private:
++        void setLang(gr::Font & font, const std::string & lang);
++        bool isCharId(const std::string & id, size_t offset, size_t length);
++        int getCharId(const std::string & id, size_t offset, size_t length);
++        int getIntValue(const std::string & id, size_t offset, size_t length);
++        size_t mnNumSettings;
++        gr::isocode maLang;
++        bool mbErrors;
++        gr::FeatureSetting maSettings[64];
++    };
++
++    union FeatId
++    {
++        gr::featid num;
++        unsigned char label[5];
++    };
++}
+Index: vcl/unx/source/gdi/makefile.mk
+===================================================================
+--- vcl/unx/source/gdi/makefile.mk	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/unx/source/gdi/makefile.mk	(.../cws/graphite01)	(Revision 273505)
+@@ -90,6 +90,10 @@
+ CFLAGS+=-DXRENDER_LINK
+ .ENDIF
+ 
++.IF "$(ENABLE_GRAPHITE)" == "TRUE"
++CFLAGS+=-DENABLE_GRAPHITE
++.ENDIF
++
+ .ENDIF	# "$(GUIBASE)"!="unx"
+ 
+ # --- Targets ------------------------------------------------------
+Index: vcl/unx/source/gdi/pspgraphics.cxx
+===================================================================
+--- vcl/unx/source/gdi/pspgraphics.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/unx/source/gdi/pspgraphics.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -51,6 +51,11 @@
+ #include <sys/stat.h>
+ #include <sys/types.h>
+ 
++#ifdef ENABLE_GRAPHITE
++#include <vcl/graphite_layout.hxx>
++#include <vcl/graphite_serverfont.hxx>
++#endif
++
+ using namespace psp;
+ using namespace rtl;
+ 
+@@ -699,9 +704,30 @@
+ 
+     Point aPos;
+     long nUnitsPerPixel = rLayout.GetUnitsPerPixel();
+-    const sal_Unicode* pText = bIsPspServerFontLayout ? static_cast<const PspServerFontLayout&>(rLayout).getTextPtr() : NULL;
+-    int nMinCharPos = bIsPspServerFontLayout ? static_cast<const PspServerFontLayout&>(rLayout).getMinCharPos() : 0;
+-    int nMaxCharPos = bIsPspServerFontLayout ? static_cast<const PspServerFontLayout&>(rLayout).getMaxCharPos() : 0;
++    const sal_Unicode* pText = NULL;
++    int nMinCharPos = 0;
++    int nMaxCharPos = 0;
++    if (bIsPspServerFontLayout)
++    {
++        const PspServerFontLayout * pPspLayout = dynamic_cast<const PspServerFontLayout*>(&rLayout);
++#ifdef ENABLE_GRAPHITE
++        const GraphiteServerFontLayout * pGrLayout = dynamic_cast<const GraphiteServerFontLayout*>(&rLayout);
++#endif
++        if (pPspLayout)
++        {
++            pText = pPspLayout->getTextPtr();
++            nMinCharPos = pPspLayout->getMinCharPos();
++            nMaxCharPos = pPspLayout->getMaxCharPos();
++        }
++#ifdef ENABLE_GRAPHITE
++        else if (pGrLayout)
++        {
++            pText = pGrLayout->getTextPtr();
++            nMinCharPos = pGrLayout->getMinCharPos();
++            nMaxCharPos = pGrLayout->getMaxCharPos();
++        }
++#endif
++    }
+     for( int nStart = 0;; )
+     {
+         int nGlyphCount = rLayout.GetNextGlyphs( nMaxGlyphs, aGlyphAry, aPos, nStart, aWidthAry, bIsPspServerFontLayout ? aCharPosAry : NULL );
+@@ -961,7 +987,21 @@
+ 
+     if( m_pServerFont[ nFallbackLevel ]
+         && !(rArgs.mnFlags & SAL_LAYOUT_DISABLE_GLYPH_PROCESSING) )
+-        pLayout = new PspServerFontLayout( *m_pPrinterGfx, *m_pServerFont[nFallbackLevel], rArgs );
++    {
++#ifdef ENABLE_GRAPHITE
++        // Is this a Graphite font?
++        if (GraphiteFontAdaptor::IsGraphiteEnabledFont(*m_pServerFont[nFallbackLevel]))
++        {
++            sal_Int32 xdpi, ydpi;
++            GetResolution(xdpi, ydpi);
++            GraphiteFontAdaptor * pGrfont = new GraphiteFontAdaptor( *m_pServerFont[nFallbackLevel], xdpi, ydpi);
++            if (!pGrfont) return NULL;
++            pLayout = new GraphiteServerFontLayout(pGrfont);
++        }
++        else
++#endif
++            pLayout = new PspServerFontLayout( *m_pPrinterGfx, *m_pServerFont[nFallbackLevel], rArgs );
++    }
+     else
+         pLayout = new PspFontLayout( *m_pPrinterGfx );
+ 
+Index: vcl/unx/source/gdi/salgdi3.cxx
+===================================================================
+--- vcl/unx/source/gdi/salgdi3.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/unx/source/gdi/salgdi3.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -82,6 +82,11 @@
+ 
+ #include <hash_set>
+ 
++#ifdef ENABLE_GRAPHITE
++#include <vcl/graphite_layout.hxx>
++#include <vcl/graphite_serverfont.hxx>
++#endif
++
+ struct cairo_surface_t;
+ struct cairo_t;
+ struct cairo_font_face_t;
+@@ -1693,11 +1698,29 @@
+ 
+ SalLayout* X11SalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel )
+ {
+-    GenericSalLayout* pLayout = NULL;
++    SalLayout* pLayout = NULL;
+ 
+     if( mpServerFont[ nFallbackLevel ]
+     && !(rArgs.mnFlags & SAL_LAYOUT_DISABLE_GLYPH_PROCESSING) )
+-        pLayout = new ServerFontLayout( *mpServerFont[ nFallbackLevel ] );
++    {
++#ifdef ENABLE_GRAPHITE
++        // Is this a Graphite font?
++        if (!bDisableGraphite_ &&
++            GraphiteFontAdaptor::IsGraphiteEnabledFont(*mpServerFont[nFallbackLevel]))
++        {
++            sal_Int32 xdpi, ydpi;
++
++            xdpi = GetDisplay()->GetResolution().A();
++            ydpi = GetDisplay()->GetResolution().B();
++
++            GraphiteFontAdaptor * pGrfont = new GraphiteFontAdaptor( *mpServerFont[nFallbackLevel], xdpi, ydpi);
++            if (!pGrfont) return NULL;
++            pLayout = new GraphiteServerFontLayout(pGrfont);
++        }
++        else
++#endif
++            pLayout = new ServerFontLayout( *mpServerFont[ nFallbackLevel ] );
++    }
+     else if( mXFont[ nFallbackLevel ] )
+         pLayout = new X11FontLayout( *mXFont[ nFallbackLevel ] );
+     else
+Index: vcl/unx/source/gdi/salgdi.cxx
+===================================================================
+--- vcl/unx/source/gdi/salgdi.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/unx/source/gdi/salgdi.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -121,6 +121,12 @@
+ 	nTextPixel_			= 0;
+ 	nTextColor_			= MAKE_SALCOLOR( 0x00, 0x00, 0x00 ); // Black
+ 
++#ifdef ENABLE_GRAPHITE
++	// check if graphite fonts have been disabled
++	static const char* pDisableGraphiteStr = getenv( "SAL_DISABLE_GRAPHITE" );
++	bDisableGraphite_		= (pDisableGraphiteStr)? TRUE : FALSE;
++#endif
++
+ 	pBrushGC_			= NULL;
+ 	nBrushPixel_			= 0;
+ 	nBrushColor_		= MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ); // White
+Index: vcl/unx/inc/salgdi.h
+===================================================================
+--- vcl/unx/inc/salgdi.h	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/unx/inc/salgdi.h	(.../cws/graphite01)	(Revision 273505)
+@@ -105,6 +105,8 @@
+     Pixel           nTextPixel_;
+     BOOL            bFontVertical_;
+ 
++    BOOL            bDisableGraphite_;
++
+     GC              pBrushGC_;      // Brush attributes
+     SalColor        nBrushColor_;
+     Pixel           nBrushPixel_;
+Index: vcl/prj/build.lst
+===================================================================
+--- vcl/prj/build.lst	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/prj/build.lst	(.../cws/graphite01)	(Revision 273505)
+@@ -1,4 +1,4 @@
+-vc	vcl	:	apple_remote BOOST:boost psprint rsc sot ucbhelper unotools ICU:icu i18npool i18nutil unoil ridljar X11_EXTENSIONS:x11_extensions offuh basegfx basebmp tools transex3 icc NULL
++vc	vcl	:	apple_remote BOOST:boost psprint rsc sot ucbhelper unotools ICU:icu GRAPHITE:graphite i18npool i18nutil unoil ridljar X11_EXTENSIONS:x11_extensions offuh basegfx basebmp tools transex3 icc NULL
+ vc	vcl										usr1	-	all	vc_mkout NULL
+ vc	vcl\inc									nmake	-	all	vc_inc NULL
+ vc	vcl\source\glyphs						nmake	-	all	vc_glyphs vc_inc NULL
+Index: vcl/util/makefile.mk
+===================================================================
+--- vcl/util/makefile.mk	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/util/makefile.mk	(.../cws/graphite01)	(Revision 273505)
+@@ -183,6 +183,16 @@
+ 			$(ICUDATALIB)		\
+             $(ICULELIB)			\
+ 			$(JVMACCESSLIB)
++
++.IF "$(GUI)" == "UNX"
++.IF "$(ENABLE_GRAPHITE)" == "TRUE"
++.IF "$(SYSTEM_GRAPHITE)" == "YES"
++SHL1STDLIBS+= $(GRAPHITE_LIBS)
++.ELSE
++SHL1STDLIBS+= $(SOLARVERSION)$/$(INPATH)$/lib$/libgraphite.a
++.ENDIF
++.ENDIF
++.ENDIF
+ SHL1USE_EXPORTS=name
+ 
+ .IF "$(GUIBASE)"=="aqua"
+@@ -198,6 +198,10 @@
+ .IF "$(USE_BUILTIN_RASTERIZER)"!=""
+     LIB1FILES +=    $(SLB)$/glyphs.lib
+     SHL1STDLIBS+=   $(FREETYPELIB)  $(PSPLIB)
++.ELSE
++.IF "$(ENABLE_GRAPHITE)" == "TRUE"
++    LIB1FILES +=    $(SLB)$/glyphs.lib
++.ENDIF
+ .ENDIF # USE_BUILTIN_RASTERIZER
+ 
+ SHL1LIBS=   $(LIB1TARGET)
+@@ -222,6 +236,14 @@
+ 
+ .IF "$(GUI)" == "WNT"
+ 
++.IF "$(ENABLE_GRAPHITE)" == "TRUE"
++.IF "$(COM)" == "GCC"
++SHL1STDLIBS += -lgraphite
++.ELSE
++SHL1STDLIBS += graphite_dll.lib
++.ENDIF
++.ENDIF
++
+ SHL1STDLIBS += $(UWINAPILIB)      \
+                $(GDI32LIB)        \
+ 			   $(GDIPLUSLIB)	  \
+Index: vcl/win/source/gdi/MAKEFILE.MK
+===================================================================
+--- vcl/win/source/gdi/MAKEFILE.MK	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/win/source/gdi/MAKEFILE.MK	(.../cws/graphite01)	(Revision 273505)
+@@ -65,6 +65,10 @@
+ 
+ EXCEPTIONSFILES=	$(SLO)$/salprn.obj
+ 
++.IF "$(ENABLE_GRAPHITE)" == "TRUE"
++CFLAGS+=-DENABLE_GRAPHITE
++.ENDIF
++
+ # --- Targets ------------------------------------------------------
+ 
+ .INCLUDE :  target.mk
+Index: vcl/win/source/gdi/salgdi3.cxx
+===================================================================
+--- vcl/win/source/gdi/salgdi3.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/win/source/gdi/salgdi3.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -74,6 +74,11 @@
+ #include <algorithm>
+ #endif
+ 
++#ifdef ENABLE_GRAPHITE
++#include <graphite/GrClient.h>
++#include <graphite/WinFont.h>
++#endif
++
+ #include <vector>
+ #include <set>
+ #include <map>
+@@ -807,6 +812,9 @@
+     mbDisableGlyphApi( false ),
+     mbHasKoreanRange( false ),
+     mbHasCJKSupport( false ),
++#ifdef ENABLE_GRAPHITE
++    mbHasGraphiteSupport( false ),
++#endif
+     mbHasArabicSupport ( false ),
+     mbAliasSymbolsLow( false ),
+     mbAliasSymbolsHigh( false ),
+@@ -865,6 +873,9 @@
+ 
+     ReadCmapTable( hDC );
+     ReadOs2Table( hDC );
++#ifdef ENABLE_GRAPHITE
++    mbHasGraphiteSupport = gr::WinFont::FontHasGraphiteTables(hDC);
++#endif
+ 
+     // even if the font works some fonts have problems with the glyph API
+     // => the heuristic below tries to figure out which fonts have the problem
+Index: vcl/win/source/gdi/winlayout.cxx
+===================================================================
+--- vcl/win/source/gdi/winlayout.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/win/source/gdi/winlayout.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -71,6 +71,17 @@
+ typedef std::hash_map<int,int> IntMap;
+ typedef std::set<int> IntSet;
+ 
++// Graphite headers
++#ifdef ENABLE_GRAPHITE
++#include <i18npool/mslangid.hxx>
++#include <graphite/GrClient.h>
++#include <graphite/WinFont.h>
++#include <graphite/Segment.h>
++#include <vcl/graphite_layout.hxx>
++#include <vcl/graphite_cache.hxx>
++#include <vcl/graphite_features.hxx>
++#endif
++
+ #define DROPPED_OUTGLYPH 0xFFFF
+ 
+ using namespace rtl;
+@@ -1767,6 +1778,8 @@
+         if( nMaxGlyphPos < n )
+             nMaxGlyphPos = n;
+     }
++	if (nMaxGlyphPos > rVisualItem.mnEndGlyphPos)
++		nMaxGlyphPos = rVisualItem.mnEndGlyphPos - 1;
+ 
+     // extend the glyph range to account for all glyphs in referenced clusters
+     if( !rVisualItem.IsRTL() ) // LTR-item
+@@ -2051,11 +2064,25 @@
+     long nDelta = nNewXPos - pVI->mnXOffset;
+     if( nStart > nMinGlyphPos )
+     {
+-        // move the glyph by expanding its left glyph
+-        int i;
++        // move the glyph by expanding its left glyph but ignore dropped glyphs
++        int i, nLastUndropped = nMinGlyphPos - 1;
+         for( i = nMinGlyphPos; i < nStart; ++i )
+-            nDelta -= mpGlyphAdvances[ i ];
+-        mpGlyphAdvances[ i-1 ] += nDelta;
++		{
++			if (mpOutGlyphs[i] != DROPPED_OUTGLYPH)
++			{
++	            nDelta -= (mpJustifications)? mpJustifications[ i ] : mpGlyphAdvances[ i ];
++				nLastUndropped = i;
++			}
++		}
++		if (nLastUndropped >= nMinGlyphPos)
++		{
++			mpGlyphAdvances[ nLastUndropped ] += nDelta;
++			if (mpJustifications) mpJustifications[ nLastUndropped ] += nDelta;
++		}
++		else
++		{
++			pVI->mnXOffset += nDelta;
++		}
+     }
+     else
+     {
+@@ -2076,11 +2103,18 @@
+         --nStart;
+     else                    // nStart<=0 for first visible glyph
+     {
+-        const VisualItem* pVI = mpVisualItems;
++        VisualItem* pVI = mpVisualItems;
+         for( int i = mnItemCount, nDummy; --i >= 0; ++pVI )
+             if( GetItemSubrange( *pVI, nStart, nDummy ) )
+                 break;
+         DBG_ASSERT( nStart <= mnGlyphCount, "USPLayout::DropG overflow" );
++		int nOffset = 0;
++		int j = pVI->mnMinGlyphPos;
++		while (mpOutGlyphs[j] == DROPPED_OUTGLYPH) j++;
++		if (j == nStart)
++		{
++			pVI->mnXOffset += ((mpJustifications)? mpJustifications[nStart] : mpGlyphAdvances[nStart]);
++		}
+     }
+ 
+     mpOutGlyphs[ nStart ] = DROPPED_OUTGLYPH;
+@@ -2137,11 +2171,12 @@
+         }
+ 
+         // handle dropped glyphs at start of visual item
+-        int nEndGlyphPos;
+-        GetItemSubrange( rVI, i, nEndGlyphPos );
++        int nMinGlyphPos, nEndGlyphPos, nOrigMinGlyphPos = rVI.mnMinGlyphPos;
++        GetItemSubrange( rVI, nMinGlyphPos, nEndGlyphPos );
++        i = nMinGlyphPos;
+         while( (mpOutGlyphs[i] == cDroppedGlyph) && (i < nEndGlyphPos) )
+         {
+-            rVI.mnXOffset += pGlyphWidths[ i ];
++            //rVI.mnXOffset += pGlyphWidths[ i ];
+             rVI.mnMinGlyphPos = ++i;
+         }
+ 
+@@ -2151,6 +2186,17 @@
+             rVI.mnEndGlyphPos = 0;
+             continue;
+         }
++		// If there are still glyphs in the cluster and mnMinGlyphPos
++		// has changed then we need to remove the dropped glyphs at start
++		// to correct logClusters, which is unsigned and relative to the 
++		// item start.
++		if (rVI.mnMinGlyphPos != nOrigMinGlyphPos)
++		{
++			// drop any glyphs in the visual item outside the range
++			for (i = nOrigMinGlyphPos; i < nMinGlyphPos; i++)
++				mpOutGlyphs[ i ] = cDroppedGlyph;
++			rVI.mnMinGlyphPos = i = nOrigMinGlyphPos;
++		}
+ 
+         // handle dropped glyphs in the middle of visual item
+         for(; i < nEndGlyphPos; ++i )
+@@ -2169,7 +2215,7 @@
+                 mpJustifications[ j ] = mpJustifications[ i ];
+             int k = mpGlyphs2Chars[ i ];
+             mpGlyphs2Chars[ j ]   = k;
+-            mpLogClusters[ k ]    = sal::static_int_cast<WORD>(j++);
++            mpLogClusters[ k ]    = sal::static_int_cast<WORD>(j++) - rVI.mnMinGlyphPos;
+         }
+ 
+         rVI.mnEndGlyphPos = j;
+@@ -2761,6 +2807,234 @@
+ 
+ #endif // USE_UNISCRIBE
+ 
++#ifdef ENABLE_GRAPHITE
++
++class GraphiteLayoutWinImpl : public GraphiteLayout
++{
++public:
++    GraphiteLayoutWinImpl(const gr::Font & font, ImplWinFontEntry & rFont)
++        throw()
++    : GraphiteLayout(font), mrFont(rFont) {};
++    virtual ~GraphiteLayoutWinImpl() throw() {};
++    virtual sal_GlyphId getKashidaGlyph(int & rWidth);
++private:
++    ImplWinFontEntry & mrFont;
++};
++
++sal_GlyphId GraphiteLayoutWinImpl::getKashidaGlyph(int & rWidth)
++{
++    rWidth = mrFont.GetMinKashidaWidth();
++    return mrFont.GetMinKashidaGlyph();
++}
++
++// This class uses the SIL Graphite engine to provide complex text layout services to the VCL
++// @author tse
++//
++class GraphiteWinLayout : public WinLayout
++{
++private:
++    mutable gr::WinFont   mpFont;
++    grutils::GrFeatureParser * mpFeatures;
++    mutable GraphiteLayoutWinImpl maImpl;
++public:
++    GraphiteWinLayout(HDC hDC, const ImplWinFontData& rWFD, ImplWinFontEntry& rWFE);
++
++    static bool IsGraphiteEnabledFont(HDC hDC) throw();
++
++    // used by upper layers
++    virtual bool  LayoutText( ImplLayoutArgs& );    // first step of layout
++    virtual void  AdjustLayout( ImplLayoutArgs& );  // adjusting after fallback etc.
++    //  virtual void  InitFont() const;
++    virtual void  DrawText( SalGraphics& ) const;
++
++    // methods using string indexing
++    virtual int   GetTextBreak( long nMaxWidth, long nCharExtra=0, int nFactor=1 ) const;
++    virtual long  FillDXArray( long* pDXArray ) const;
++
++    virtual void  GetCaretPositions( int nArraySize, long* pCaretXArray ) const;
++
++    // methods using glyph indexing
++    virtual int   GetNextGlyphs(int nLen, sal_GlyphId* pGlyphIdxAry, ::Point & rPos, int&,
++                      long* pGlyphAdvAry = 0, int* pCharPosAry = 0 ) const;
++
++    // used by glyph+font+script fallback
++    virtual void    MoveGlyph( int nStart, long nNewXPos );
++    virtual void    DropGlyph( int nStart );
++    virtual void    Simplify( bool bIsBase );
++    ~GraphiteWinLayout() { delete mpFeatures; mpFeatures = NULL; };
++protected:
++    virtual void    ReplaceDC(gr::Segment & segment) const;
++    virtual void    RestoreDC(gr::Segment & segment) const;
++};
++
++bool GraphiteWinLayout::IsGraphiteEnabledFont(HDC hDC) throw()
++{
++  return gr::WinFont::FontHasGraphiteTables(hDC);
++}
++
++GraphiteWinLayout::GraphiteWinLayout(HDC hDC, const ImplWinFontData& rWFD, ImplWinFontEntry& rWFE) throw()
++  : WinLayout(hDC, rWFD, rWFE), mpFont(hDC),
++    maImpl(mpFont, rWFE)
++{
++    const rtl::OString aLang = MsLangId::convertLanguageToIsoByteString( rWFE.maFontSelData.meLanguage );
++    rtl::OString name = rtl::OUStringToOString(
++        rWFE.maFontSelData.maTargetName, RTL_TEXTENCODING_UTF8 );
++    sal_Int32 nFeat = name.indexOf(grutils::GrFeatureParser::FEAT_PREFIX) + 1;
++    if (nFeat > 0)
++    {
++        rtl::OString aFeat = name.copy(nFeat, name.getLength() - nFeat);
++        mpFeatures = new grutils::GrFeatureParser(mpFont, aFeat.getStr(), aLang.getStr());
++    }
++    else
++    {
++        mpFeatures = new grutils::GrFeatureParser(mpFont, aLang.getStr());
++    }
++    maImpl.SetFeatures(mpFeatures);
++}
++
++void GraphiteWinLayout::ReplaceDC(gr::Segment & segment) const
++{
++    COLORREF color = GetTextColor(mhDC);
++    dynamic_cast<gr::WinFont&>(segment.getFont()).replaceDC(mhDC);
++    SetTextColor(mhDC, color);
++}
++
++void GraphiteWinLayout::RestoreDC(gr::Segment & segment) const
++{
++    dynamic_cast<gr::WinFont&>(segment.getFont()).restoreDC();
++}
++
++bool GraphiteWinLayout::LayoutText( ImplLayoutArgs & args)
++{
++    HFONT hUnRotatedFont;
++    if (args.mnOrientation)
++    {
++        // Graphite gets very confused if the font is rotated
++        LOGFONTW aLogFont;
++        ::GetObjectW( mhFont, sizeof(LOGFONTW), &aLogFont);
++        aLogFont.lfEscapement = 0;
++        aLogFont.lfOrientation = 0;
++        hUnRotatedFont = ::CreateFontIndirectW( &aLogFont);
++        ::SelectFont(mhDC, hUnRotatedFont);
++    }
++    WinLayout::AdjustLayout(args);
++    mpFont.replaceDC(mhDC);
++    maImpl.SetFontScale(WinLayout::mfFontScale);
++    //bool succeeded = maImpl.LayoutText(args);
++#ifdef GRCACHE
++    GrSegRecord * pSegRecord = NULL;
++    gr::Segment * pSegment = maImpl.CreateSegment(args, &pSegRecord);
++#else
++    gr::Segment * pSegment = maImpl.CreateSegment(args);
++#endif
++    bool bSucceeded = false;
++    if (pSegment)
++    {
++        // replace the DC on the font within the segment
++        ReplaceDC(*pSegment);
++        // create glyph vectors
++#ifdef GRCACHE
++        bSucceeded = maImpl.LayoutGlyphs(args, pSegment, pSegRecord);
++#else
++        bSucceeded = maImpl.LayoutGlyphs(args, pSegment);
++#endif
++        // restore original DC
++        RestoreDC(*pSegment);
++#ifdef GRCACHE
++        if (pSegRecord) pSegRecord->unlock();
++        else delete pSegment;
++#else
++        delete pSegment;
++#endif
++    }
++    mpFont.restoreDC();
++    if (args.mnOrientation)
++    {
++        // restore the rotated font
++        ::SelectFont(mhDC, mhFont);
++        ::DeleteObject(hUnRotatedFont);
++    }
++    return bSucceeded;
++}
++
++void  GraphiteWinLayout::AdjustLayout(ImplLayoutArgs& rArgs)
++{
++    WinLayout::AdjustLayout(rArgs);
++    maImpl.DrawBase() = WinLayout::maDrawBase;
++    maImpl.DrawOffset() = WinLayout::maDrawOffset;
++    if ( (rArgs.mnFlags & SAL_LAYOUT_BIDI_RTL) && rArgs.mpDXArray)
++    {
++        mrWinFontEntry.InitKashidaHandling(mhDC);
++    }
++    maImpl.AdjustLayout(rArgs);
++}
++
++void GraphiteWinLayout::DrawText(SalGraphics &sal_graphics) const
++{
++    HFONT hOrigFont = DisableFontScaling();
++    HDC aHDC = static_cast<WinSalGraphics&>(sal_graphics).mhDC;
++    maImpl.DrawBase() = WinLayout::maDrawBase;
++    maImpl.DrawOffset() = WinLayout::maDrawOffset;
++    const int MAX_GLYPHS = 2;
++    sal_GlyphId glyphIntStr[MAX_GLYPHS];
++    WORD glyphWStr[MAX_GLYPHS];
++    int glyphIndex = 0;
++    Point aPos(0,0);
++    int nGlyphs = 0;
++    do
++    {
++        nGlyphs = maImpl.GetNextGlyphs(1, glyphIntStr, aPos, glyphIndex);
++        if (nGlyphs < 1)
++          break;
++        std::copy(glyphIntStr, glyphIntStr + nGlyphs, glyphWStr);
++        ::ExtTextOutW(aHDC, aPos.X(), aPos.Y(), ETO_GLYPH_INDEX,
++		              NULL, (LPCWSTR)&(glyphWStr), nGlyphs, NULL);
++    } while (nGlyphs);
++    if( hOrigFont )
++          DeleteFont( SelectFont( mhDC, hOrigFont ) );
++}
++
++int GraphiteWinLayout::GetTextBreak( long nMaxWidth, long nCharExtra, int nFactor ) const
++{
++    mpFont.replaceDC(mhDC);
++    int nBreak = maImpl.GetTextBreak(nMaxWidth, nCharExtra, nFactor);
++    mpFont.restoreDC();
++    return nBreak;
++}
++
++long  GraphiteWinLayout::FillDXArray( long* pDXArray ) const
++{
++    return maImpl.FillDXArray(pDXArray);
++}
++
++void GraphiteWinLayout::GetCaretPositions( int nArraySize, long* pCaretXArray ) const
++{
++	maImpl.GetCaretPositions(nArraySize, pCaretXArray);
++}
++
++int GraphiteWinLayout::GetNextGlyphs( int length, sal_GlyphId* glyph_out,
++        ::Point & pos_out, int &glyph_slot, long * glyph_adv, int *char_index) const
++{
++    maImpl.DrawBase() = WinLayout::maDrawBase;
++    maImpl.DrawOffset() = WinLayout::maDrawOffset;
++    return maImpl.GetNextGlyphs(length, glyph_out, pos_out, glyph_slot, glyph_adv, char_index);
++}
++
++void GraphiteWinLayout::MoveGlyph( int glyph_idx, long new_x_pos )
++{
++	maImpl.MoveGlyph(glyph_idx, new_x_pos);
++}
++
++void GraphiteWinLayout::DropGlyph( int glyph_idx )
++{
++	maImpl.DropGlyph(glyph_idx);
++}
++
++void GraphiteWinLayout::Simplify( bool is_base )
++{
++	maImpl.Simplify(is_base);
++}
++#endif // ENABLE_GRAPHITE
+ // =======================================================================
+ 
+ SalLayout* WinSalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel )
+@@ -2776,6 +3050,11 @@
+     if( !(rArgs.mnFlags & SAL_LAYOUT_COMPLEX_DISABLED)
+     &&   (aUspModule || (bUspEnabled && InitUSP())) )   // CTL layout engine
+     {
++#ifdef ENABLE_GRAPHITE
++        if (rFontFace.SupportsGraphite())
++            pWinLayout = new GraphiteWinLayout(mhDC, rFontFace, rFontInstance);
++        else
++#endif // ENABLE_GRAPHITE
+         // script complexity is determined in upper layers
+         pWinLayout = new UniscribeLayout( mhDC, rFontFace, rFontInstance );
+         // NOTE: it must be guaranteed that the WinSalGraphics lives longer than
+@@ -2798,7 +3077,12 @@
+         BYTE eCharSet = ANSI_CHARSET;
+         if( mpLogFont )
+             eCharSet = mpLogFont->lfCharSet;
+-        pWinLayout = new SimpleWinLayout( mhDC, eCharSet, rFontFace, rFontInstance );
++#ifdef ENABLE_GRAPHITE
++        if (rFontFace.SupportsGraphite())
++            pWinLayout = new GraphiteWinLayout(mhDC, rFontFace, rFontInstance);
++        else
++#endif // ENABLE_GRAPHITE
++            pWinLayout = new SimpleWinLayout( mhDC, eCharSet, rFontFace, rFontInstance );
+     }
+ 
+     if( mfFontScale != 1.0 )
+
+Eigenschaftsänderungen: vcl/win/source/gdi/winlayout.cxx
+___________________________________________________________________
+Gelöscht: svn:executable
+   - *
+
+Index: vcl/win/source/window/MAKEFILE.MK
+===================================================================
+--- vcl/win/source/window/MAKEFILE.MK	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/win/source/window/MAKEFILE.MK	(.../cws/graphite01)	(Revision 273505)
+@@ -60,6 +60,10 @@
+ EXCEPTIONSFILES=   $(SLO)$/salframe.obj
+ .ENDIF
+ 
++.IF "$(ENABLE_GRAPHITE)" == "TRUE"
++CFLAGS+=-DENABLE_GRAPHITE
++.ENDIF
++
+ # --- Targets ------------------------------------------------------
+ 
+ .INCLUDE :	target.mk
+Index: vcl/win/inc/salgdi.h
+===================================================================
+--- vcl/win/inc/salgdi.h	(.../tags/DEV300_m49)	(Revision 273505)
++++ vcl/win/inc/salgdi.h	(.../cws/graphite01)	(Revision 273505)
+@@ -81,6 +81,9 @@
+     bool                    SupportsArabic() const      { return mbHasArabicSupport; }
+     bool                    AliasSymbolsHigh() const    { return mbAliasSymbolsHigh; }
+     bool                    AliasSymbolsLow() const     { return mbAliasSymbolsLow; }
++#ifdef ENABLE_GRAPHITE
++	bool                    SupportsGraphite() const    { return mbHasGraphiteSupport; }
++#endif
+ 
+     ImplFontCharMap*        GetImplFontCharMap() const;
+     const Ucs2SIntMap* GetEncodingVector() const { return mpEncodingVector; }
+@@ -97,6 +100,9 @@
+     mutable bool                    mbDisableGlyphApi;
+     mutable bool                    mbHasKoreanRange;
+     mutable bool                    mbHasCJKSupport;
++#ifdef ENABLE_GRAPHITE
++    mutable bool                    mbHasGraphiteSupport;
++#endif
+     mutable bool                    mbHasArabicSupport;
+     mutable ImplFontCharMap*        mpUnicodeMap;
+     mutable const Ucs2SIntMap*      mpEncodingVector;
+Index: configure.in
+===================================================================
+--- configure.in	(.../tags/DEV300_m49)	(Revision 273505)
++++ configure.in	(.../cws/graphite01)	(Revision 273505)
+@@ -29,6 +29,12 @@
+ [  --without-gpc           Use the internal polygon clipping code instead of
+                           the external GPC polygon clipping library.
+ ],,if test ! -e ./external/gpc/gpc.c && test ! -e ./external/gpc/gpc.h; then without_gpc=yes; fi)
++AC_ARG_ENABLE(graphite,
++[  --enable-graphite       Enables the compilation of Graphite smart font rendering
++],,)
++AC_ARG_WITH(system-graphite,
++[  --with-system-graphite    use graphite library already installed on system
++],,)
+ AC_ARG_ENABLE(ldap,
+ [  --disable-ldap          Disables the use of LDAP backend via Netscape/Mozilla
+                           or OpenLDAP LDAP SDK
+@@ -3484,24 +3490,6 @@
+ AC_SUBST(SYSTEM_EXPAT)
+ 
+ dnl ===================================================================
+-dnl Check for system libwpd
+-dnl ===================================================================
+-AC_MSG_CHECKING([which libwpd to use])
+-if test -n "$with_system_libwpd" -o -n "$with_system_libs" && \
+-        test "$with_system_libwpd" != "no"; then
+-    AC_MSG_RESULT([external])
+-    SYSTEM_LIBWPD=YES
+-    PKG_CHECK_MODULES( LIBWPD, libwpd-0.8 )
+-else
+-    AC_MSG_RESULT([internal])
+-    SYSTEM_LIBWPD=NO
+-    BUILD_TYPE="$BUILD_TYPE LIBWPD"
+-fi
+-AC_SUBST(SYSTEM_LIBWPD)
+-AC_SUBST(LIBWPD_CFLAGS)
+-AC_SUBST(LIBWPD_LIBS)
+-
+-dnl ===================================================================
+ dnl Check whether freetype is available
+ dnl ===================================================================
+ if test  "$test_freetype" = "yes"; then
+@@ -3550,6 +3538,24 @@
+ fi
+ 
+ dnl ===================================================================
++dnl Check for system libwpd
++dnl ===================================================================
++AC_MSG_CHECKING([which libwpd to use])
++if test -n "$with_system_libwpd" -o -n "$with_system_libs" && \
++        test "$with_system_libwpd" != "no"; then
++    AC_MSG_RESULT([external])
++    SYSTEM_LIBWPD=YES
++    PKG_CHECK_MODULES( LIBWPD, libwpd-0.8 )
++else
++    AC_MSG_RESULT([internal])
++    SYSTEM_LIBWPD=NO
++    BUILD_TYPE="$BUILD_TYPE LIBWPD"
++fi
++AC_SUBST(SYSTEM_LIBWPD)
++AC_SUBST(LIBWPD_CFLAGS)
++AC_SUBST(LIBWPD_LIBS)
++
++dnl ===================================================================
+ dnl Check for system libxslt
+ dnl ===================================================================
+ AC_MSG_CHECKING([which libxslt to use])
+@@ -4307,6 +4313,39 @@
+ AC_SUBST(SYSTEM_GENCMN)
+ 
+ dnl ===================================================================
++dnl Graphite
++dnl ===================================================================
++
++AC_MSG_CHECKING([whether to enable graphite support])
++if test "$_os" = "WINNT" -o "$_os" = "Linux" && test "z$enable_graphite" == "z" -o "$enable_graphite" != "no" ; then
++    AC_MSG_RESULT([yes])
++    ENABLE_GRAPHITE="TRUE"
++    AC_MSG_CHECKING([which graphite to use])
++    if test -n "$with_system_graphite" -o -n "$with_system_libs" && \
++        test "$with_system_graphite" != "no"; then
++        AC_MSG_RESULT([external])
++        SYSTEM_GRAPHITE=YES
++        PKG_CHECK_MODULES( GRAPHITE, silgraphite )
++	AC_MSG_CHECKING([STL compatibility])
++	if test "$WITH_STLPORT" != "no"; then
++		AC_MSG_ERROR([to use system graphite you need to use --without-stlport])
++	else
++		AC_MSG_RESULT([OK])	
++	fi
++    else
++        AC_MSG_RESULT([internal])
++        SYSTEM_GRAPHITE=NO
++        BUILD_TYPE="$BUILD_TYPE GRAPHITE"
++    fi
++else
++   AC_MSG_RESULT([no])
++fi
++AC_SUBST(ENABLE_GRAPHITE)
++AC_SUBST(SYSTEM_GRAPHITE)
++AC_SUBST(GRAPHITE_LIBS)
++AC_SUBST(GRAPHITE_CFLAGS)
++
++dnl ===================================================================
+ dnl Checks for libraries.
+ dnl ===================================================================
+ dnl Check for Mac OS X native GUI, which may is now required; the X11 build is no longer supported
+Index: drawinglayer/source/processor2d/vclprocessor2d.cxx
+===================================================================
+--- drawinglayer/source/processor2d/vclprocessor2d.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ drawinglayer/source/processor2d/vclprocessor2d.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -189,6 +189,7 @@
+ 
+                         aScale.getY(), 
+                         fRotate, 
++                        rTextCandidate.getLocale(),
+                         *mpOutputDevice));
+ 
+                     if(!basegfx::fTools::equal(aScale.getX(), aScale.getY()))
+@@ -209,7 +210,8 @@
+                                 rTextCandidate.getFontAttributes(), 
+                                 aScale.getX(), 
+                                 aScale.getY(), 
+-                                fRotate, 
++                                fRotate,
++                                rTextCandidate.getLocale(), 
+                                 *mpOutputDevice);
+ 						}
+                     }
+Index: drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx
+===================================================================
+--- drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -305,7 +305,7 @@
+ 
+                 // TextLayouterDevice is needed to get metrics for text decorations like
+                 // underline/strikeout/emphasis marks from it. For setup, the font size is needed
+-			    aTextLayouter.setFontAttributes(getFontAttributes(), rDecTrans.getScale().getX(), rDecTrans.getScale().getY());
++			    aTextLayouter.setFontAttributes(getFontAttributes(), rDecTrans.getScale().getX(), rDecTrans.getScale().getY(), getLocale());
+ 
+ 				// get text width
+ 				double fTextWidth(0.0);
+@@ -526,7 +526,7 @@
+ 					if(bNoDXArray)
+ 					{
+ 						// ..but only completely when no DXArray
+-						aTextLayouter.setFontAttributes(getFontAttributes(), rDecTrans.getScale().getX(), rDecTrans.getScale().getY());
++						aTextLayouter.setFontAttributes(getFontAttributes(), rDecTrans.getScale().getX(), rDecTrans.getScale().getY(),getLocale());
+ 					}
+ 
+ 					// do iterate over single words
+Index: drawinglayer/source/primitive2d/textlayoutdevice.cxx
+===================================================================
+--- drawinglayer/source/primitive2d/textlayoutdevice.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ drawinglayer/source/primitive2d/textlayoutdevice.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -41,6 +41,7 @@
+ #include <vcl/virdev.hxx>
+ #include <vcl/font.hxx>
+ #include <vcl/metric.hxx>
++#include <i18npool/mslangid.hxx>
+ #include <drawinglayer/primitive2d/textprimitive2d.hxx>
+ 
+ //////////////////////////////////////////////////////////////////////////////
+@@ -165,14 +166,14 @@
+ 			mrDevice.SetFont( rFont );
+ 		}
+ 
+-		void TextLayouterDevice::setFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DHomMatrix& rTransform)
++		void TextLayouterDevice::setFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DHomMatrix& rTransform, const ::com::sun::star::lang::Locale & rLocale)
+ 		{
+-			setFont(getVclFontFromFontAttributes(rFontAttributes, rTransform, mrDevice));
++			setFont(getVclFontFromFontAttributes(rFontAttributes, rTransform, rLocale, mrDevice));
+ 		}
+ 
+-		void TextLayouterDevice::setFontAttributes(const FontAttributes& rFontAttributes, double fFontScaleX, double fFontScaleY)
++		void TextLayouterDevice::setFontAttributes(const FontAttributes& rFontAttributes, double fFontScaleX, double fFontScaleY, const ::com::sun::star::lang::Locale & rLocale)
+ 		{
+-			setFont(getVclFontFromFontAttributes(rFontAttributes, fFontScaleX, fFontScaleY, 0.0, mrDevice));
++			setFont(getVclFontFromFontAttributes(rFontAttributes, fFontScaleX, fFontScaleY, 0.0, rLocale, mrDevice));
+         }
+ 
+         double TextLayouterDevice::getOverlineOffset() const
+@@ -288,6 +289,7 @@
+ 		Font getVclFontFromFontAttributes(
+             const FontAttributes& rFontAttributes,
+             const basegfx::B2DHomMatrix& rTransform,
++            const ::com::sun::star::lang::Locale & rLocale,
+             const OutputDevice& rOutDev)
+ 		{
+ 			// decompose matrix to have position and size of text
+@@ -296,7 +298,7 @@
+ 
+             rTransform.decompose(aScale, aTranslate, fRotate, fShearX);
+ 
+-            return getVclFontFromFontAttributes(rFontAttributes, aScale.getX(), aScale.getY(), fRotate, rOutDev);
++            return getVclFontFromFontAttributes(rFontAttributes, aScale.getX(), aScale.getY(), fRotate, rLocale, rOutDev);
+ 		}
+ 
+ 		Font getVclFontFromFontAttributes(
+@@ -304,6 +306,7 @@
+             double fFontScaleX,
+             double fFontScaleY,
+             double fFontRotation,
++            const ::com::sun::star::lang::Locale & rLocale,
+             const OutputDevice& /*rOutDev*/)
+ 		{
+ 			sal_uInt32 nWidth(basegfx::fround(fabs(fFontScaleX)));
+@@ -323,6 +326,7 @@
+ 			aRetval.SetWeight(static_cast<FontWeight>(rFontAttributes.getWeight()));
+ 			aRetval.SetItalic(rFontAttributes.getItalic() ? ITALIC_NORMAL : ITALIC_NONE);
+ 			aRetval.SetOutline(rFontAttributes.getOutline());
++            aRetval.SetLanguage(MsLangId::convertLocaleToLanguage(rLocale));
+ 
+ #ifdef WIN32
+ 			// #100424# use higher precision
+Index: drawinglayer/source/primitive2d/textprimitive2d.cxx
+===================================================================
+--- drawinglayer/source/primitive2d/textprimitive2d.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ drawinglayer/source/primitive2d/textprimitive2d.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -145,7 +145,7 @@
+ 
+ 					// prepare textlayoutdevice
+ 					TextLayouterDevice aTextLayouter;
+-					aTextLayouter.setFontAttributes(getFontAttributes(), aFontScale.getX(), aFontScale.getY());
++					aTextLayouter.setFontAttributes(getFontAttributes(), aFontScale.getX(), aFontScale.getY(), getLocale());
+ #ifdef WIN32
+                     // when under Windows and the font is unequally scaled, need to correct font X-Scaling factor
+                     if(bCorrectScale)
+@@ -300,7 +300,7 @@
+ 
+ 					// prepare textlayoutdevice
+ 					TextLayouterDevice aTextLayouter;
+-					aTextLayouter.setFontAttributes(getFontAttributes(), aFontScale.getX(), aFontScale.getY());
++					aTextLayouter.setFontAttributes(getFontAttributes(), aFontScale.getX(), aFontScale.getY(), getLocale());
+ 
+ 					// get basic text range
+ 					basegfx::B2DRange aNewRange(aTextLayouter.getTextBoundRect(getText(), getTextPosition(), getTextLength()));
+Index: drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx
+===================================================================
+--- drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx	(.../cws/graphite01)	(Revision 273505)
+@@ -41,6 +41,7 @@
+ #include <tools/poly.hxx>
+ #include <basegfx/range/b2drange.hxx>
+ #include <vector>
++#include <com/sun/star/lang/Locale.hpp>
+ 
+ //////////////////////////////////////////////////////////////////////////////
+ // predefines
+@@ -75,8 +76,8 @@
+ 			~TextLayouterDevice();
+ 
+ 			void setFont(const Font& rFont);
+-			void setFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DHomMatrix& rTransform);
+-			void setFontAttributes(const FontAttributes& rFontAttributes, double fFontScaleX, double fFontScaleY);
++			void setFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DHomMatrix& rTransform, const ::com::sun::star::lang::Locale & rLocale);
++			void setFontAttributes(const FontAttributes& rFontAttributes, double fFontScaleX, double fFontScaleY, const ::com::sun::star::lang::Locale & rLocale);
+ 
+ 			double getTextHeight() const;
+             double getOverlineHeight() const;
+@@ -119,11 +120,13 @@
+             double fFontScaleX,
+             double fFontScaleY,
+             double fFontRotation,
++            const ::com::sun::star::lang::Locale & rLocale,
+             const OutputDevice& rOutDev);
+ 
+         Font getVclFontFromFontAttributes(
+             const FontAttributes& rFontAttributes,
+             const basegfx::B2DHomMatrix& rTransform,
++            const ::com::sun::star::lang::Locale & rLocale,
+             const OutputDevice& rOutDev);
+ 
+         FontAttributes getFontAttributesFromVclFont(basegfx::B2DVector& rSize, const Font& rFont, bool bRTL, bool bBiDiStrong);
+Index: drawinglayer/util/makefile.mk
+===================================================================
+--- drawinglayer/util/makefile.mk	(.../tags/DEV300_m49)	(Revision 273505)
++++ drawinglayer/util/makefile.mk	(.../cws/graphite01)	(Revision 273505)
+@@ -72,6 +72,7 @@
+ 		$(CPPUHELPERLIB)	\
+ 		$(CPPULIB)			\
+ 		$(AVMEDIALIB)		\
++		$(I18NISOLANGLIB)	\
+ 		$(COMPHELPERLIB)
+ 
+ SHL1DEF=	$(MISC)$/$(SHL1TARGET).def
+Index: sc/source/core/data/patattr.cxx
+===================================================================
+--- sc/source/core/data/patattr.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ sc/source/core/data/patattr.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -258,14 +258,16 @@
+ 	FontEmphasisMark eEmphasis;
+ 	FontRelief eRelief;
+ 	Color aColor;
++	LanguageType eLang;
+ 
+-	USHORT nFontId, nHeightId, nWeightId, nPostureId;
++	USHORT nFontId, nHeightId, nWeightId, nPostureId, nLangId;
+ 	if ( nScript == SCRIPTTYPE_ASIAN )
+ 	{
+ 		nFontId    = ATTR_CJK_FONT;
+ 		nHeightId  = ATTR_CJK_FONT_HEIGHT;
+ 		nWeightId  = ATTR_CJK_FONT_WEIGHT;
+ 		nPostureId = ATTR_CJK_FONT_POSTURE;
++		nLangId    = ATTR_CJK_FONT_LANGUAGE;
+ 	}
+ 	else if ( nScript == SCRIPTTYPE_COMPLEX )
+ 	{
+@@ -273,6 +275,7 @@
+ 		nHeightId  = ATTR_CTL_FONT_HEIGHT;
+ 		nWeightId  = ATTR_CTL_FONT_WEIGHT;
+ 		nPostureId = ATTR_CTL_FONT_POSTURE;
++		nLangId    = ATTR_CTL_FONT_LANGUAGE;
+ 	}
+ 	else
+ 	{
+@@ -280,6 +283,7 @@
+ 		nHeightId  = ATTR_FONT_HEIGHT;
+ 		nWeightId  = ATTR_FONT_WEIGHT;
+ 		nPostureId = ATTR_FONT_POSTURE;
++		nLangId    = ATTR_FONT_LANGUAGE;
+ 	}
+ 
+ 	if ( pCondSet )
+@@ -337,6 +341,10 @@
+ 		if ( pCondSet->GetItemState( ATTR_FONT_COLOR, TRUE, &pItem ) != SFX_ITEM_SET )
+             pItem = &rItemSet.Get( ATTR_FONT_COLOR );
+ 		aColor = ((const SvxColorItem*)pItem)->GetValue();
++
++		if ( pCondSet->GetItemState( nLangId, TRUE, &pItem ) != SFX_ITEM_SET )
++			pItem = &rItemSet.Get( nLangId );
++		eLang = ((const SvxLanguageItem*)pItem)->GetLanguage();
+ 	}
+     else    // alles aus rItemSet
+ 	{
+@@ -365,6 +373,9 @@
+                         rItemSet.Get( ATTR_FONT_RELIEF )).GetValue();
+ 		aColor = ((const SvxColorItem&)
+                         rItemSet.Get( ATTR_FONT_COLOR )).GetValue();
++		// for graphite language features
++		eLang =
++		((const SvxLanguageItem&)rItemSet.Get( nLangId )).GetLanguage();
+ 	}
+ 	DBG_ASSERT(pFontAttr,"nanu?");
+ 
+@@ -381,6 +392,8 @@
+ 	rFont.SetCharSet( pFontAttr->GetCharSet() );
+ 	rFont.SetPitch( pFontAttr->GetPitch() );
+ 
++	rFont.SetLanguage(eLang);
++
+ 	//	Groesse
+ 
+ 	if ( pOutDev != NULL )
+Index: sw/source/core/text/itrform2.cxx
+===================================================================
+--- sw/source/core/text/itrform2.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ sw/source/core/text/itrform2.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -1973,6 +1973,7 @@
+         nReformat -= 2;
+ 
+ #ifndef QUARTZ
++#ifndef ENABLE_GRAPHITE
+         // --> FME 2004-09-27 #i28795#, #i34607#, #i38388#
+         // step back six(!) more characters for complex scripts
+         // this is required e.g., for Khmer (thank you, Javier!)
+@@ -1981,6 +1982,10 @@
+         if( ::i18n::ScriptType::COMPLEX == rSI.ScriptType( nReformat ) )
+             nMaxContext = 6;
+ #else
++        // Some Graphite fonts need context for scripts not marked as complex
++        static const xub_StrLen nMaxContext = 10;
++#endif
++#else
+         // some fonts like Quartz's Zapfino need more context
+         // TODO: query FontInfo for maximum unicode context
+         static const xub_StrLen nMaxContext = 8;
+Index: sw/source/core/text/makefile.mk
+===================================================================
+--- sw/source/core/text/makefile.mk	(.../tags/DEV300_m49)	(Revision 273505)
++++ sw/source/core/text/makefile.mk	(.../cws/graphite01)	(Revision 273505)
+@@ -45,6 +45,9 @@
+ CDEFS+=-Dmydebug
+ .ENDIF
+ 
++.IF "$(ENABLE_GRAPHITE)" == "TRUE"
++CFLAGS+=-DENABLE_GRAPHITE
++.ENDIF
+ # --- Files --------------------------------------------------------
+ 
+ .IF "$(product)$(cap)" == ""
+Index: sw/source/core/text/porlay.cxx
+===================================================================
+--- sw/source/core/text/porlay.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ sw/source/core/text/porlay.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -45,6 +45,7 @@
+ #include <porrst.hxx>		// SwHangingPortion
+ #include <pormulti.hxx> 	// SwMultiPortion
+ #include <breakit.hxx>
++#include <unicode/uchar.h>
+ #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
+ #include <com/sun/star/i18n/ScriptType.hdl>
+ #endif
+@@ -1036,7 +1037,26 @@
+         }
+         // <--
+ 
+-        aScriptChg.Insert( nChg, nCnt );
++        // special case for dotted circle since it can be used with complex
++        // before a mark, so we want it associated with the mark's script
++        if (nChg < rTxt.Len() && nChg > 0 && (i18n::ScriptType::WEAK ==
++            pBreakIt->xBreak->getScriptType(rTxt,nChg - 1)))
++        {
++            int8_t nType = u_charType(rTxt.GetChar(nChg) );
++            if (nType == U_NON_SPACING_MARK || nType == U_ENCLOSING_MARK ||
++                nType == U_COMBINING_SPACING_MARK )
++            {
++                aScriptChg.Insert( nChg - 1, nCnt );
++            }
++            else
++            {
++                aScriptChg.Insert( nChg, nCnt );
++            }
++        }
++        else
++        {
++            aScriptChg.Insert( nChg, nCnt );
++        }
+         aScriptType.Insert( nScript, nCnt++ );
+ 
+         // if current script is asian, we search for compressable characters
+Index: sw/source/core/txtnode/fntcache.cxx
+===================================================================
+--- sw/source/core/txtnode/fntcache.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ sw/source/core/txtnode/fntcache.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -152,6 +152,7 @@
+ 				 || UNDERLINE_NONE != aFont.GetOverline()
+ 				 || STRIKEOUT_NONE != aFont.GetStrikeout() )
+ 				 && !aFont.IsWordLineMode();
++	aFont.SetLanguage(rFont.GetLanguage());
+ }
+ 
+ SwFntObj::~SwFntObj()
+Index: sw/source/core/bastyp/breakit.cxx
+===================================================================
+--- sw/source/core/bastyp/breakit.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ sw/source/core/bastyp/breakit.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -32,6 +32,7 @@
+ #include "precompiled_sw.hxx"
+ 
+ #include "breakit.hxx"
++#include <unicode/uchar.h>
+ #include <com/sun/star/lang/XMultiServiceFactory.hpp>
+ #ifndef _COM_SUN_STAR_I18N_SCRIPTTYPE_HDL_
+ #include <com/sun/star/i18n/ScriptType.hdl>
+@@ -119,6 +120,18 @@
+ 			--nPos;
+ 		nScript = xBreak->getScriptType( rTxt, nPos );
+ 		sal_Int32 nChgPos = 0;
++        if ( i18n::ScriptType::WEAK == nScript && nPos + 1 < rTxt.Len() )
++        {
++            // A weak character followed by a mark may be meant to combine with
++            // the mark, so prefer the following character's script
++            switch ( u_charType(rTxt.GetChar(nPos + 1) ) ) {
++            case U_NON_SPACING_MARK:
++            case U_ENCLOSING_MARK:
++            case U_COMBINING_SPACING_MARK:
++                nScript = xBreak->getScriptType( rTxt, nPos+1 );
++                break;
++            }
++        }
+         if( i18n::ScriptType::WEAK == nScript && nPos &&
+ 			0 < (nChgPos = xBreak->beginOfScript( rTxt, nPos, nScript )) )
+ 			nScript = xBreak->getScriptType( rTxt, nChgPos-1 );
+Index: graphite/graphite-2.3.1.patch
+===================================================================
+--- graphite/graphite-2.3.1.patch	(.../tags/DEV300_m49)	(Revision 0)
++++ graphite/graphite-2.3.1.patch	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,1551 @@
++--- misc/build/silgraphite-2.3.1/engine/include/graphite/GrCommon.h	2007-12-20 12:51:13.000000000 +0000
+++++ misc/build/silgraphite-2.3.1/engine/include/graphite/GrCommon.h	2007-12-20 12:50:53.000000000 +0000
++@@ -41,7 +41,7 @@
++ // Provided the client includes GrClient.h first this #define is
++ // picked up by all files.
++ 
++-//#define gr gr2
+++#define gr gr3ooo
++ 
++ // Project headers
++ #include "GrPlatform.h"
++
++
++--- misc/build/silgraphite-2.3.1/wrappers/win32/WinFont.h	2008-02-06 19:20:23.437500000 +0000
+++++ misc/build/silgraphite-2.3.1/wrappers/win32/WinFont.h	2008-02-06 19:25:01.406250000 +0000
++@@ -27,6 +27,10 @@
++ #include "GrClient.h"
++ #include "Font.h"
++ 
+++#ifdef _STLPORT_VERSION
+++namespace stdext = std;
+++#endif
+++
++ namespace gr
++ {
++ 
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrTableManager.cpp	2008-02-06 19:32:56.015625000 +0000
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrTableManager.cpp	2008-02-06 19:33:09.734375000 +0000
++@@ -25,8 +25,8 @@
++ DEFINE_THIS_FILE
++ #ifndef _WIN32
++ #include <stdlib.h>
++-#include <math.h>
++ #endif
+++#include <math.h>
++ 
++ //:>********************************************************************************************
++ //:>	Forward declarations
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrEngine.cpp	2008-01-31 17:02:28.000000000 +0000
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrEngine.cpp	2008-02-07 22:44:00.875000000 +0000
++@@ -158,12 +158,12 @@
++ GrEngine::~GrEngine()
++ {
++ 	DestroyEverything();
++-	#ifdef _MSC_VER
++-	if (!_CrtCheckMemory())
++-	{
++-		OutputDebugString(L"bad memory");
++-	}
++-	#endif
+++//	#ifdef _MSC_VER
+++//	if (!_CrtCheckMemory())
+++//	{
+++//		OutputDebugString(L"bad memory");
+++//	}
+++//	#endif
++ }
++ 
++ /*----------------------------------------------------------------------------------------------
++@@ -172,12 +172,12 @@
++ void GrEngine::DestroyEverything()
++ {
++ 	DestroyContents();
++-	#ifdef _MSC_VER
++-	if (!_CrtCheckMemory())
++-	{
++-		OutputDebugString(L"bad memory");
++-	}
++-	#endif
+++//	#ifdef _MSC_VER
+++//	if (!_CrtCheckMemory())
+++//	{
+++//		OutputDebugString(L"bad memory");
+++//	}
+++//	#endif
++ 
++ 	m_strCtrlFileReg.erase();
++ 	m_strCtrlFileBold.erase();
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrSlotStream.cpp.orig	2009-02-04 12:53:26.000000000 +0700
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrSlotStream.cpp	2009-02-07 17:39:12.000000000 +0700
++@@ -1094,7 +1094,7 @@
++ 	case kdircLRO:
++ 	case kdircLRE:
++ 	case kdircPdfL:
++-    case kdircLlb:
+++	case kdircLlb:
++ 		return false;
++ 
++ 	case kdircR:
++@@ -1104,6 +1104,7 @@
++ 	case kdircRLO:
++ 	case kdircRLE:
++ 	case kdircPdfR:
+++	case kdircRlb:
++ 		return true;
++ 
++ 	case kdircNeutral:
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrFeature.cpp.orig	2009-01-22 05:36:42.000000000 +0700
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrFeature.cpp	2009-02-26 20:12:15.221917600 +0700
++@@ -206,13 +206,22 @@
++ 
++ 	m_cbOffset0 = (lsbf)(m_prglang[0].cbOffsetBIG);
++ 
++-	Assert((lsbf)(m_prglang[m_clang].cFeaturesBIG) == 0); // bogus entry has no settings
++-	cb = (lsbf)(m_prglang[m_clang].cbOffsetBIG) - m_cbOffset0;
++-	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);
+++	if ((lsbf)(m_prglang[m_clang].cFeaturesBIG) == 0) // bogus entry has no settings
+++	{
+++		cb = (lsbf)(m_prglang[m_clang].cbOffsetBIG) - m_cbOffset0;
+++		if (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);
+++		}
+++		else return false;
+++	}
+++	else
+++	{
+++		return false;
+++	}
++ 
++ 	return true;
++ }
++--- misc/build/silgraphite-2.3.1/wrappers/win32/WinFont.cpp.orig	2009-03-31 20:55:51.336268100 +0700
+++++ misc/build/silgraphite-2.3.1/wrappers/win32/WinFont.cpp	2009-03-31 20:55:57.326668100 +0700
++@@ -767,7 +767,7 @@
++ ----------------------------------------------------------------------------------------------*/
++ void WinFont::FontHandleCache::DeleteFont(HFONT hfont)
++ {
++-	if (!hfont || !m_bValid)
+++	if (!hfont || !m_bValid || m_hmlffcv.size() == 0)
++ 		return;
++ 
++ 	// find the font in the hash map
++
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrPass.h.orig	2009-05-01 09:16:10.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrPass.h	2009-05-01 09:22:13.000000000 +0630
++@@ -197,7 +197,7 @@
++ 	bool ReadFromFont(GrIStream & grstrm, int fxdSilfVersion, int fxdRuleVersion, int nOffset);
++ 	void InitializeWithNoRules();
++ 
++-	virtual void SetTopDirLevel(int n)
+++	virtual void SetTopDirLevel(int /*n*/)
++ 	{	// only GrBidiPass does anything interesting
++ 	}
++ 
++@@ -253,13 +253,13 @@
++ 		m_pzpst->SetResyncSkip(n);
++ 	}
++ 
++-	virtual void DoCleanUpSegMin(GrTableManager * ptman,
++-		GrSlotStream * psstrmIn, int islotInitReadPos, GrSlotStream * psstrmOut)
+++	virtual void DoCleanUpSegMin(GrTableManager * /*ptman*/,
+++		GrSlotStream * /*psstrmIn*/, int /*islotInitReadPos*/, GrSlotStream * /*psstrmOut*/)
++ 	{
++ 	}
++ 
++-	virtual void DoCleanUpSegLim(GrTableManager * ptman, GrSlotStream * psstrmOut,
++-		TrWsHandling twsh)
+++	virtual void DoCleanUpSegLim(GrTableManager * /*ptman*/, GrSlotStream * /*psstrmOut*/,
+++		TrWsHandling /*twsh*/)
++ 	{
++ 	}
++ 
++@@ -383,8 +383,8 @@
++ 	void MapChunks(GrSlotStream * psstrmIn, GrSlotStream * psstrmOut,
++ 		int islotChunkI, int islotChunkO, int cslotReprocessed);
++ 
++-	virtual void Unattach(GrSlotStream * psstrmIn, int islotIn,	// GrPosPass overrides
++-		GrSlotStream * psstrmOut, int islotOut, int islotLB)
+++	virtual void Unattach(GrSlotStream * /*psstrmIn*/, int /*islotIn*/,	// GrPosPass overrides
+++		GrSlotStream * /*psstrmOut*/, int /*islotOut*/, int /*islotLB*/)
++ 	{
++ 	}
++ 
++@@ -500,8 +500,8 @@
++ 
++ protected:
++ 	//	Irrelevant when generating glyphs.
++-	virtual void RunRule(GrTableManager *, int ruln,
++-		GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput)
+++	virtual void RunRule(GrTableManager *, int /*ruln*/,
+++		GrSlotStream * /*psstrmInput*/, GrSlotStream * /*psstrmOutput*/)
++ 	{
++ 		Assert(false);
++ 	}
++--- misc/build/silgraphite-2.3.1/engine/include/graphite/GrMstypes.h.orig	2009-05-01 09:12:55.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/include/graphite/GrMstypes.h	2009-05-01 09:14:41.000000000 +0630
++@@ -24,11 +24,11 @@
++ 
++ typedef signed long	    HRESULT;
++ 
++-inline const long InterlockedIncrement(long *const intr_lck) {
+++inline long InterlockedIncrement(long *const intr_lck) {
++ 	return ++*intr_lck;
++ }
++ 
++-inline const long InterlockedDecrement(long *const intr_lck) {
+++inline long InterlockedDecrement(long *const intr_lck) {
++ 	return --*intr_lck;
++ }
++ 
++--- misc/build/silgraphite-2.3.1/engine/src/font/Font.cpp.orig	2009-05-01 09:08:32.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/font/Font.cpp	2009-05-01 09:11:38.000000000 +0630
++@@ -626,7 +626,7 @@
++ 		Assert(false);
++ 		m_ifeat = m_cfeat;
++ 	}
++-	else if (m_ifeat + n < 0)
+++	else if (static_cast<int>(m_ifeat) + n < 0)
++ 	{
++ 		// Can't decrement.
++ 		Assert(false);
++@@ -727,7 +727,7 @@
++ 		Assert(false);
++ 		m_ifset = m_cfset;
++ 	}
++-	if (m_ifset + n < 0)
+++	if (static_cast<int>(m_ifset) + n < 0)
++ 	{
++ 		// Can't decrement.
++ 		Assert(false);
++@@ -820,7 +820,7 @@
++ 		Assert(false);
++ 		m_ilang = m_clang;
++ 	}
++-	else if (m_ilang + n < 0)
+++	else if (static_cast<int>(m_ilang) + n < 0)
++ 	{
++ 		// Can't decrement.
++ 		Assert(false);
++@@ -906,7 +906,7 @@
++ 		Assert(false);
++ 		m_ilang = m_clang;
++ 	}
++-	else if (m_ilang + n < 0)
+++	else if (static_cast<int>(m_ilang) + n < 0)
++ 	{
++ 		// Can't decrement.
++ 		Assert(false);
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrSlotState.h.orig	2009-05-01 09:30:03.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrSlotState.h	2009-05-01 09:38:31.000000000 +0630
++@@ -308,7 +308,11 @@
++ 	{
++ 		return m_islotPosPass;
++ 	}
++-	void SetPosPassIndex(int islot, bool fInputToPosPass1)
+++#ifdef NDEBUG
+++	void SetPosPassIndex(int islot, bool /*fInputToPosPass1*/)
+++#else
+++	void SetPosPassIndex(int islot, bool fInputToPosPass1)
+++#endif
++ 	{
++ 		// If we're resetting it, it should be to the same value as before:
++ 		Assert(fInputToPosPass1 || m_islotPosPass == kNotYetSet || m_islotPosPass == islot);
++@@ -386,12 +386,12 @@
++ 		return (IsInitialLineBreak(chwLB) || IsFinalLineBreak(chwLB));
++ 		//return (m_chwGlyphID == chwLB); // TODO: remove
++ 	}
++-	bool IsInitialLineBreak(gid16 chwLB)
+++	bool IsInitialLineBreak(gid16 /*chwLB*/)
++ 	{
++ 		return (m_spsl == kspslLbInitial);
++ 		//return (IsLineBreak(chwLB) && m_fInitialLB == true); // TODO: remove
++ 	}
++-	bool IsFinalLineBreak(gid16 chwLB)
+++	bool IsFinalLineBreak(gid16 /*chwLB*/)
++ 	{
++ 		return (m_spsl == kspslLbFinal);
++ 		//return (IsLineBreak(chwLB) && m_fInitialLB == false); // TODO: remove
++@@ -475,7 +475,7 @@
++ 		return m_mAttachAtX;
++ 	}
++ 
++-	int AttachWithX(GrTableManager * ptman, GrSlotStream * psstrm)
+++	int AttachWithX(GrTableManager * /*ptman*/, GrSlotStream * /*psstrm*/)
++ 	{
++ 		if (m_mAttachAtX == kNotYetSet)
++ 		{
++@@ -646,7 +646,7 @@
++ 	{
++ 		return ClusterBbLeft(psstrm) + xs;
++ 	}
++-	float ClusterRsb(GrSlotStream * psstrm, float xs)
+++	float ClusterRsb(GrSlotStream * /*psstrm*/, float xs)
++ 	{
++ 		return ClusterAdvWidthFrom(xs) - ClusterBbRightFrom(xs);
++ 	}
++@@ -668,19 +668,19 @@
++ 	{
++ 		return ClusterBbRightFrom(Base(psstrm)->ClusterRootOffset());
++ 	}
++-	float ClusterBbTop(GrSlotStream * psstrm)
+++	float ClusterBbTop(GrSlotStream * /*psstrm*/)
++ 	{
++ 		return m_ysClusterBbTop;
++ 	}
++-	float ClusterBbBottom(GrSlotStream * psstrm)
+++	float ClusterBbBottom(GrSlotStream * /*psstrm*/)
++ 	{
++ 		return m_ysClusterBbBottom;
++ 	}
++-	float ClusterBbWidth(GrSlotStream * psstrm)
+++	float ClusterBbWidth(GrSlotStream * /*psstrm*/)
++ 	{
++ 		return m_xsClusterBbRight - m_xsClusterBbLeft + 1;
++ 	}
++-	float ClusterBbHeight(GrSlotStream * psstrm)
+++	float ClusterBbHeight(GrSlotStream * /*psstrm*/)
++ 	{
++ 		return m_ysClusterBbTop - m_ysClusterBbBottom + 1;
++ 	}
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrSlotStream.h.orig	2009-05-01 09:39:27.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrSlotStream.h	2009-05-01 09:40:20.000000000 +0630
++@@ -107,7 +107,7 @@
++ 		ReleaseSlots(0, m_vpslot.size());
++ 	}
++ 
++-	void ReleaseSlots(int islotMin, int islotLim)
+++	void ReleaseSlots(int /*islotMin*/, int /*islotLim*/)
++ 	{
++ 		//	A slot stream is responsible for deleting the slot states that it created,
++ 		//	that is, the ones whose modified tag equals this stream's pass index.
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrSlotStream.h.orig	2009-05-01 10:35:34.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrSlotStream.h	2009-05-01 10:38:22.000000000 +0630
++@@ -260,12 +260,16 @@
++ 
++ 	void MarkFullyWritten();
++ 
+++#ifdef NDEBUG
+++	void SetSegMin(int islot, bool /*fAdjusting*/ = false)
+++#else
++ 	void SetSegMin(int islot, bool fAdjusting = false)
+++#endif
++ 	{
++ 		Assert(fAdjusting || m_islotSegMin == -1 || m_islotSegMin == islot);
++ 		m_islotSegMin = islot;
++ 	}
++-	void SetSegMinToWritePos(bool fMod = true)
+++	void SetSegMinToWritePos(bool /*fMod*/ = true)
++ 	{
++ 		if (m_islotSegMin == -1)
++ 			m_islotSegMin = m_islotWritePos;
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrClassTable.h.orig	2009-05-01 10:39:27.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrClassTable.h	2009-05-01 10:41:44.000000000 +0630
++@@ -54,7 +54,11 @@
++ 	/*------------------------------------------------------------------------------------------
++ 		Copy the raw memory into the instance.
++ 	------------------------------------------------------------------------------------------*/
+++#ifdef NDEBUG
+++	void CopyFrom(data16 * pchwStart, int /*cchw*/)
+++#else
++ 	void CopyFrom(data16 * pchwStart, int cchw)
+++#endif
++ 	{
++ 		m_cgixBIG = pchwStart[0];
++ 		m_digixBIGInit = pchwStart[1];
++--- misc/build/silgraphite-2.3.1/engine/src/font/TtfUtil.cpp.orig	2009-05-01 10:44:33.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/font/TtfUtil.cpp	2009-05-01 10:48:47.000000000 +0630
++@@ -1108,8 +1108,8 @@
++ 	{ // loca entries are two bytes and have been divided by two
++ 		if (nGlyphId <= (lLocaSize >> 1) - 1) // allow sentinel value to be accessed
++ 		{
++-			const uint16 * pTable = reinterpret_cast<const uint16 *>(pLoca);
++-			return (read(pTable[nGlyphId]) << 1);
+++			const uint16 * pTableLoca = reinterpret_cast<const uint16 *>(pLoca);
+++			return (read(pTableLoca[nGlyphId]) << 1);
++ 		}
++ 	}
++ 	
++@@ -1117,8 +1117,8 @@
++ 	{ // loca entries are four bytes
++ 		if (nGlyphId <= (lLocaSize >> 2) - 1)
++ 		{
++-			const uint32 * pTable = reinterpret_cast<const uint32 *>(pLoca);
++-			return read(pTable[nGlyphId]);
+++			const uint32 * pTableLoca = reinterpret_cast<const uint32 *>(pLoca);
+++			return read(pTableLoca[nGlyphId]);
++ 		}
++ 	}
++ 
++@@ -1586,7 +1586,7 @@
++ 
++ 	for (size_t i = 0; i < cCompId; i++)
++ 	{
++-		void * pSimpleGlyf = GlyfLookup(static_cast<gr::gid16>(rgnCompId[i]), 
+++		pSimpleGlyf = GlyfLookup(static_cast<gr::gid16>(rgnCompId[i]), 
++ 										pGlyf, pLoca, lLocaSize, pHead);
++ 		if (pSimpleGlyf == NULL) {return false;}
++ 
++@@ -1748,7 +1748,7 @@
++ ----------------------------------------------------------------------------------------------*/
++ bool GlyfPoints(gr::gid16 nGlyphId, const void * pGlyf, 
++ 		const void * pLoca, size_t lLocaSize, const void * pHead, 
++-		const int * prgnContourEndPoint, size_t cnEndPoints, 
+++		const int * /*prgnContourEndPoint*/, size_t /*cnEndPoints*/, 
++ 		int * prgnX, int * prgnY, bool * prgfOnCurve, size_t cnPoints)
++ {
++ 	std::fill_n(prgnX, cnPoints, INT_MAX);
++
++--- misc/build/silgraphite-2.3.1/engine/src/segment/FileInput.cpp	2009-01-22 05:06:42.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/FileInput.cpp	2009-05-01 11:18:02.000000000 +0630
++@@ -80,7 +80,7 @@
++ #ifdef GR_FW
++ bool GrBufferIStream::Open(std::wstring stuFileName, int kMode)
++ #else
++-bool GrBufferIStream::Open(const char * pcFileName, std::ios::openmode kMode)
+++bool GrBufferIStream::Open(const char * /*pcFileName*/, std::ios::openmode /*kMode*/)
++ #endif
++ {
++ 	Assert(false); // use OpenBuffer
++--- misc/build/silgraphite-2.3.1/engine/src/font/FileFont.cpp	2009-01-22 05:06:42.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/font/FileFont.cpp	2009-05-01 11:17:34.000000000 +0630
++@@ -233,7 +233,7 @@
++ FileFont::readTable(int /*TableId*/ tid, size_t & size)
++ {
++ 	const TableId tableId = TableId(tid);
++-	bool isValid = true;
+++	bool isTableValid = true;
++ 	size_t lOffset = 0, lSize = 0;
++ 	if (!m_pTableCache)
++ 	{
++@@ -245,9 +245,9 @@
++ 	size = m_pTableCache->getTableSize(tableId);
++ 	// check whether it is already in the cache
++ 	if (pTable) return pTable;
++-	isValid &= TtfUtil::GetTableInfo(tableId, m_pHeader, m_pTableDir, 
+++	isTableValid &= TtfUtil::GetTableInfo(tableId, m_pHeader, m_pTableDir, 
++ 			lOffset, lSize);
++-	if (!isValid) 
+++	if (!isTableValid) 
++ 		return NULL;
++ 	fseek(m_pfile, lOffset, SEEK_SET);
++ 	// only allocate if needed
++@@ -255,16 +255,16 @@
++ 	
++ 	if (!pTable) 
++ 	{
++-		isValid = false;
+++		isTableValid = false;
++ 		return NULL;
++ 	}
++ 	size_t bytesRead = fread(pTable, 1, lSize, m_pfile);
++-	isValid = bytesRead == lSize;
++-	if (isValid)
+++	isTableValid = bytesRead == lSize;
+++	if (isTableValid)
++ 	{
++-		isValid &= TtfUtil::CheckTable(tableId, pTable, lSize);
+++		isTableValid &= TtfUtil::CheckTable(tableId, pTable, lSize);
++ 	}
++-	if (!isValid) 
+++	if (!isTableValid) 
++ 	{
++ 		return 0;
++ 	}
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrCharStream.cpp	2009-05-01 11:31:36.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrCharStream.cpp	2009-05-01 11:28:38.000000000 +0630
++@@ -417,8 +417,11 @@
++ 	return true;
++ */
++ }
+++#ifdef NDEBUG
+++bool GrCharStream::AtUnicodeCharBoundary(utf8 * prgchs, int cchs, int ichs, UtfType /*utf*/)
+++#else
++-
++ bool GrCharStream::AtUnicodeCharBoundary(utf8 * prgchs, int cchs, int ichs, UtfType utf)
+++#endif
++ {
++ 	Assert(ichs >= 0);
++ 	Assert(ichs <= cchs);
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrEngine.cpp.orig	2009-05-01 11:35:12.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrEngine.cpp	2009-05-01 11:40:28.000000000 +0630
++@@ -417,7 +417,11 @@
++ 	@return The supported script direction(s). If more than one, the application is
++ 	responsible for choosing the most appropriate.
++ ----------------------------------------------------------------------------------------------*/
+++#ifdef NDEBUG
+++GrResult GrEngine::get_ScriptDirection(unsigned int * pgrfsdc, OLECHAR * /*prgchwErrMsg*/, int /*cchMaxErrMsg*/)
+++#else
++ GrResult GrEngine::get_ScriptDirection(unsigned int * pgrfsdc, OLECHAR * prgchwErrMsg, int cchMaxErrMsg)
+++#endif
++ {
++ 	ChkGrOutPtr(pgrfsdc);
++ 	ChkGrArrayArg(prgchwErrMsg, cchMaxErrMsg);
++@@ -789,7 +793,7 @@
++ 	Record a system error indicating a bad error in rendering using a supposedly valid font.
++ 	OBSOLETE
++ ----------------------------------------------------------------------------------------------*/
++-void GrEngine::RecordFontRunError(OLECHAR * prgchwErrMsg, int cchMax, GrResult res)
+++void GrEngine::RecordFontRunError(OLECHAR * prgchwErrMsg, int cchMax, GrResult /*res*/)
++ {
++ 	if (prgchwErrMsg == NULL || cchMax == 0)
++ 		return;
++@@ -970,7 +974,7 @@
++ /*----------------------------------------------------------------------------------------------
++ 	Return whether the text is asking for bold and/or italic text.
++ ----------------------------------------------------------------------------------------------*/
++-void GrEngine::GetStyles(Font * pfont, int ichwMin, bool * pfBold, bool * pfItalic)
+++void GrEngine::GetStyles(Font * pfont, int /*ichwMin*/, bool * pfBold, bool * pfItalic)
++ {
++ 	*pfBold = pfont->bold();
++ 	*pfItalic = pfont->italic();
++@@ -981,7 +985,11 @@
++ 	Should only be called when we know we are using a base font, or when we are reading
++ 	the base font to see if it is valid.
++ ----------------------------------------------------------------------------------------------*/
+++#ifdef NDEBUG
+++void GrEngine::SwitchGraphicsFont(bool /*fBase*/)
+++#else
++ void GrEngine::SwitchGraphicsFont(bool fBase)
+++#endif
++ {
++ 	Assert(!fBase || m_stuBaseFaceName.size() > 0);
++ 
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrEngine.cpp.orig	2009-05-01 12:10:09.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrEngine.cpp	2009-05-01 12:10:54.000000000 +0630
++@@ -1143,7 +1143,7 @@
++ 		m_chwJShrink0 = 0xffff;
++ 		m_chwJStep0 = 0xffff;
++ 		m_chwJWeight0 = 0xffff;
++-		for (int i = 0; i < m_cJLevels; i++)
+++		for (i = 0; i < m_cJLevels; i++)
++ 		{
++ 			//	justification glyph attribute IDs
++ 			bTmp = grstrm.ReadByteFromFont();
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrFeature.cpp.orig	2009-05-01 12:12:29.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrFeature.cpp	2009-05-01 12:13:05.000000000 +0630
++@@ -186,7 +186,7 @@
++ /*----------------------------------------------------------------------------------------------
++ 	Read the languages from the font.
++ ----------------------------------------------------------------------------------------------*/
++-bool GrLangTable::ReadFromFont(GrIStream * pgrstrm, int fxdVersion)
+++bool GrLangTable::ReadFromFont(GrIStream * pgrstrm, int /*fxdVersion*/)
++ {
++ 	GrIStream & grstrm = *pgrstrm;
++ 	
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrFSM.cpp.orig	2009-05-01 12:14:43.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrFSM.cpp	2009-05-01 12:30:05.000000000 +0630
++@@ -46,7 +46,7 @@
++ 	Fill in the FSM by reading from the font stream.
++ 	Assumes the stream is in the correct position.
++ ----------------------------------------------------------------------------------------------*/
++-bool GrFSM::ReadFromFont(GrIStream & grstrm, int fxdVersion)
+++bool GrFSM::ReadFromFont(GrIStream & grstrm, int /*fxdVersion*/)
++ {
++ 	short snTmp;
++ 	
++@@ -138,7 +138,7 @@
++ 	Fill in the FSM's state table by reading from the font stream.
++ 	Assumes the stream is in the correct position.
++ ----------------------------------------------------------------------------------------------*/
++-bool GrFSM::ReadStateTableFromFont(GrIStream & grstrm, int fxdVersion)
+++bool GrFSM::ReadStateTableFromFont(GrIStream & grstrm, int /*fxdVersion*/)
++ {
++ 	int cCells = ((m_crow - m_crowFinal) * m_ccol);
++ 	m_prgrowTransitions = new short[cCells];
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrPassActionCode.cpp.orig	2009-05-01 12:33:36.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrPassActionCode.cpp	2009-05-01 12:43:56.000000000 +0630
++@@ -632,8 +632,13 @@
++ /*----------------------------------------------------------------------------------------------
++ 	We are finished processing a slot; go on to the next slot, or possibly go backwards.
++ ----------------------------------------------------------------------------------------------*/
++-void GrPass::DoNext(GrTableManager * ptman,
++-	int cslot, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut)
+++#ifdef NDEBUG
+++void GrPass::DoNext(GrTableManager * /*ptman*/,
+++	int /*cslot*/, GrSlotStream * /*psstrmIn*/, GrSlotStream * /*psstrmOut*/)
+++#else
+++void GrPass::DoNext(GrTableManager * /*ptman*/,
+++	int cslot, GrSlotStream * /*psstrmIn*/, GrSlotStream * /*psstrmOut*/)
+++#endif
++ {
++ 	gAssert(cslot == 1);	// for now anyway
++ }
++@@ -830,7 +830,7 @@
++ 	@param psstrmIn / Out		- input/output streams
++ ----------------------------------------------------------------------------------------------*/
++ void GrPass::DoPutSubs3(GrTableManager * ptman, bool fInserting,
++-	int cslotSel1, int nSelClass1, int cslotSel2, int nSelClass2, int cslotSel3, int nSelClass3,
+++	int cslotSel1, int nSelClass1, int cslotSel2, int nSelClass2, int /*cslotSel3*/, int nSelClass3,
++ 	int nReplacementClass,
++ 	GrSlotStream * psstrmIn, GrSlotStream * psstrmOut)
++ {
++@@ -888,7 +893,7 @@
++ 	Common part of all the DoPutSubs... methods.
++ ----------------------------------------------------------------------------------------------*/
++ void GrPass::DoPutSubsAux(GrTableManager * ptman, bool fInserting, gid16 nGlyphReplacement,
++-	GrSlotStream * psstrmIn, GrSlotStream * psstrmOut, GrSlotState * pslotNextInput,
+++	GrSlotStream * /*psstrmIn*/, GrSlotStream * psstrmOut, GrSlotState * pslotNextInput,
++ 	bool fAtSegMin, bool fAtSegLim)
++ {
++ 	EngineState * pengst = ptman->State();
++@@ -924,7 +929,7 @@
++ 	and its after-assoc to the slot before it. This makes it basically unselectable.
++ 	OBSOLETE - handled by slot initialization code
++ ----------------------------------------------------------------------------------------------*/
++-void GrPass::SetNeutralAssocs(GrSlotState * pslotNew, GrSlotStream * psstrmIn)
+++void GrPass::SetNeutralAssocs(GrSlotState * pslotNew, GrSlotStream * /*psstrmIn*/)
++ {
++ 	pslotNew->ClearAssocs();
++ }
++@@ -957,7 +962,7 @@
++ 	@param fInserting			- whether current slot was inserted
++ 	@param psstrmIn / Out		- input/output streams
++ ----------------------------------------------------------------------------------------------*/
++-void GrPass::DoAssoc(int cnAssocs, std::vector<int> & vnAssocs, bool fInserting,
+++void GrPass::DoAssoc(int cnAssocs, std::vector<int> & vnAssocs, bool /*fInserting*/,
++ 	GrSlotStream * psstrmIn, GrSlotStream * psstrmOut)
++ {
++ 	gAssert((unsigned)cnAssocs == vnAssocs.size());
++@@ -997,7 +1002,11 @@
++ 	@param vnStack				- stack to read value from
++ 	@param psstrmIn / Out		- input/output streams
++ ----------------------------------------------------------------------------------------------*/
+++#ifdef NDEBUG
+++void GrPass::DoSetAttr(GrTableManager * ptman, ActionCommand op, bool /*fInserting*/,
+++#else
++ void GrPass::DoSetAttr(GrTableManager * ptman, ActionCommand op, bool fInserting,
+++#endif
++ 	SlotAttrName slat, int slati, std::vector<int> & vnStack,
++ 	GrSlotStream * psstrmIn, GrSlotStream * psstrmOut)
++ {
++@@ -1192,7 +1197,7 @@
++ 	@param psstrmIn				- input stream
++ ----------------------------------------------------------------------------------------------*/
++ void GrPass::DoPushSlotAttr(GrTableManager * ptman,
++-	int nSlotRef, bool fInserting,
+++	int nSlotRef, bool /*fInserting*/,
++ 	SlotAttrName slat, int slati, std::vector<int> & vnStack,
++ 	GrSlotStream * psstrmIn, GrSlotStream * psstrmOut)
++ {
++@@ -1282,7 +1287,7 @@
++ 	@param vnStack				- stack to push onto
++ 	@param psstrmIn				- input stream
++ ----------------------------------------------------------------------------------------------*/
++-void GrPass::DoPushGlyphAttr(GrTableManager * ptman, int nSlotRef, bool fInserting,
+++void GrPass::DoPushGlyphAttr(GrTableManager * ptman, int nSlotRef, bool /*fInserting*/,
++ 	int nGlyphAttr,
++ 	std::vector<int> & vnStack, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut)
++ {
++@@ -1307,7 +1312,7 @@
++ 	@param vnStack				- stack to push onto
++ 	@param psstrmIn				- input stream
++ ----------------------------------------------------------------------------------------------*/
++-void GrPass::DoPushAttToGlyphAttr(GrTableManager * ptman, int nSlotRef, bool fInserting,
+++void GrPass::DoPushAttToGlyphAttr(GrTableManager * ptman, int nSlotRef, bool /*fInserting*/,
++ 	int nGlyphAttr, std::vector<int> & vnStack,
++ 	GrSlotStream * psstrmIn, GrSlotStream * psstrmOut)
++ {
++@@ -1337,7 +1342,7 @@
++ 	@param vnStack				- stack to push onto
++ 	@param psstrmIn				- input stream
++ ----------------------------------------------------------------------------------------------*/
++-void GrPass::DoPushGlyphMetric(GrTableManager * ptman, int nSlotRef, bool fInserting,
+++void GrPass::DoPushGlyphMetric(GrTableManager * ptman, int nSlotRef, bool /*fInserting*/,
++ 	int nGlyphAttr, int nAttLevel,
++ 	std::vector<int> & vnStack, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut)
++ {
++@@ -1364,7 +1369,7 @@
++ 	@param psstrmIn				- input stream
++ 	@param psstrmOut			- output stream
++ ----------------------------------------------------------------------------------------------*/
++-void GrPass::DoPushAttToGlyphMetric(GrTableManager * ptman, int nSlotRef, bool fInserting,
+++void GrPass::DoPushAttToGlyphMetric(GrTableManager * ptman, int nSlotRef, bool /*fInserting*/,
++ 	int nGlyphAttr, int nAttLevel,
++ 	std::vector<int> & vnStack,
++ 	GrSlotStream * psstrmIn, GrSlotStream * psstrmOut)
++@@ -1435,7 +1440,11 @@
++ 	@param psstrmIn				- input stream
++ 	@param psstrmOut			- output stream
++ ----------------------------------------------------------------------------------------------*/
++-void GrPass::DoPushFeatValue(GrTableManager * ptman, int nSlotRef, bool fInserting,
+++#ifdef NDEBUG
+++void GrPass::DoPushFeatValue(GrTableManager * /*ptman*/, int nSlotRef, bool /*fInserting*/,
+++#else
+++void GrPass::DoPushFeatValue(GrTableManager * /*ptman*/, int nSlotRef, bool fInserting,
+++#endif
++ 	int nFeat, std::vector<int> & vnStack, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut)
++ {
++ 	gAssert(!fInserting);
++
++
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrPass.cpp	2009-05-01 13:37:32.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrPass.cpp.orig	2009-05-01 13:04:04.000000000 +0630
++@@ -465,7 +465,7 @@
++ void GrBidiPass::ExtendOutput(GrTableManager * ptman,
++ 	GrSlotStream* psstrmIn, GrSlotStream* psstrmOut,
++ 	int cslotNeededByNext, TrWsHandling twsh,
++-	int * pnRet, int * pcslotGot, int * pislotFinalBreak)
+++	int * pnRet, int * pcslotGot, int * /*pislotFinalBreak*/)
++ {
++ 	Assert(psstrmIn->SlotsToReprocess() == 0);
++ 
++@@ -776,7 +776,7 @@
++ int GrPass::ExtendFinalOutput(GrTableManager * ptman,
++ 	GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput,
++ 	float xsSpaceAllotted, bool fWidthIsCharCount, bool fInfiniteWidth,
++-	bool fHaveLineBreak, bool fMustBacktrack, LineBrk lbMax, TrWsHandling twsh,
+++	bool fHaveLineBreak, bool fMustBacktrack, LineBrk /*lbMax*/, TrWsHandling twsh,
++ 	int * pislotLB, float * pxsWidth)
++ {
++ 	EngineState * pengst = ptman->State();
++@@ -897,7 +897,11 @@
++ 	Remove undesirable trailing white-space.
++ ----------------------------------------------------------------------------------------------*/
++ int GrPass::RemoveTrailingWhiteSpace(GrTableManager * ptman, GrSlotStream * psstrmOut,
+++#ifdef NDEBUG
+++	TrWsHandling /*twsh*/, int * pislotFinalBreak)
+++#else
++	TrWsHandling twsh, int * pislotFinalBreak)
+++#endif
++ {
++ 	EngineState * pengst = ptman->State();
++ 
++@@ -944,7 +944,7 @@
++ 	should never be necessary if they've set up their tables right.
++ ----------------------------------------------------------------------------------------------*/
++ void GrPass::CheckInputProgress(GrSlotStream * psstrmInput, GrSlotStream * psstrmOutput,
++-	int islotOrigInput)
+++	int /*islotOrigInput*/)
++ {
++ 	int islotInput = psstrmInput->ReadPosForNextGet();
++ //	Assert(islotInput >= islotOrigInput); -- no longer true now that we can back up
++@@ -1752,7 +1752,7 @@
++ ----------------------------------------------------------------------------------------------*/
++ int GrPass::Unwind(GrTableManager * ptman,
++ 	int islotChanged, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut,
++-	bool fFirst)
+++	bool /*fFirst*/)
++ {
++ 	//	Back up the number of slots required for the longest rule context,
++ 	//	but if we land in the middle of a chunk, go forward to its boundary.
++@@ -1824,7 +1824,7 @@
++ ----------------------------------------------------------------------------------------------*/
++ int GrBidiPass::Unwind(GrTableManager * ptman,
++ 	int islotChanged, GrSlotStream * psstrmIn, GrSlotStream * psstrmOut,
++-	bool fFirst)
+++	bool /*fFirst*/)
++ {
++ 	int islotIn;
++ 	int islotOut;
++@@ -1901,8 +1901,8 @@
++ 	OBSOLETE
++ ----------------------------------------------------------------------------------------------*/
++ //:Ignore
++-void GrPosPass::Unattach(GrSlotStream * psstrmIn, int islotIn,
++-	GrSlotStream * psstrmOut, int islotOut, int islotLB)
+++void GrPosPass::Unattach(GrSlotStream * /*psstrmIn*/, int /*islotIn*/,
+++	GrSlotStream * /*psstrmOut*/, int /*islotOut*/, int /*islotLB*/)
++ {
++ 	//	Because this is a positioning pass, there is a one-to-one correspondence between
++ 	//	the slots in the input and the slots in the output. Thus we can make simplifying
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrSlotStream.cpp.orig	2009-05-01 14:47:31.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrSlotStream.cpp	2009-05-01 14:54:13.000000000 +0630
++@@ -194,7 +194,11 @@
++ 	@param fNullOkay	- true if it's okay to return NULL in the situation where we're asking
++ 							for something before the beginning of the stream
++ ----------------------------------------------------------------------------------------------*/
+++#ifdef NDEBUG
+++GrSlotState * GrSlotStream::PeekBack(int dislot, bool /*fNullOkay*/)
+++#else
++ GrSlotState * GrSlotStream::PeekBack(int dislot, bool fNullOkay)
+++#endif
++ {
++ 	Assert(dislot < 0);
++ 	if (dislot < m_islotRuleStartWrite * -1)
++@@ -1323,7 +1323,7 @@
++ 	@param islotMin			- first slot that is officially part of the segment (after initial LB)
++ ----------------------------------------------------------------------------------------------*/
++ int GrSlotStream::MakeSegmentBreak(GrTableManager * ptman,
++-	int islotPrevBreak, bool fInsertedLB, int islotStartTry,
+++	int /*islotPrevBreak*/, bool /*fInsertedLB*/, int islotStartTry,
++ 	LineBrk lb, TrWsHandling twsh, int islotMin,
++ 	LineBrk * plbNextToTry)
++ {
++@@ -1577,7 +1577,11 @@
++ 	Return the break weight of the given slot, which should be a line-break.
++ 	OBSOLETE??
++ ----------------------------------------------------------------------------------------------*/
+++#ifdef NDEBUG
+++LineBrk GrSlotStream::BreakWeightAt(gid16 /*chwLB*/, int islot)
+++#else
++ LineBrk GrSlotStream::BreakWeightAt(gid16 chwLB, int islot)
+++#endif
++ {	
++ 	GrSlotState * pslot = GetSlotAt(islot);
++ 	Assert(pslot->IsLineBreak(chwLB));
++@@ -1770,7 +1770,7 @@
++ 	@param fBackingUp		- this chunk results in the stream position moving backwards,
++ 								so clear anything we're backing over
++ ----------------------------------------------------------------------------------------------*/
++-void GrSlotStream::MapInputChunk(int islotInputMin, int islotOutputMin, int islotInputLim,
+++void GrSlotStream::MapInputChunk(int islotInputMin, int islotOutputMin, int /*islotInputLim*/,
++ 	bool fSkipChunkStart, bool fBackingUp)
++ {
++ 	Assert(AssertValid());
++@@ -1829,7 +1829,7 @@
++ 	@param fBackingUp		- this chunk results in the stream position moving backwards,
++ 								so clear anything we're backing over
++ ----------------------------------------------------------------------------------------------*/
++-void GrSlotStream::MapOutputChunk(int islotOutputMin, int islotInputMin, int islotOutputLim,
+++void GrSlotStream::MapOutputChunk(int islotOutputMin, int islotInputMin, int /*islotOutputLim*/,
++ 	bool fSkipChunkStart, int cslotReprocess, bool fBackingUp)
++ {
++ 	Assert(AssertValid());
++@@ -1864,7 +1864,7 @@
++ 	Ensure that the chunk maps for a pair of streams match properly. The recipient is
++ 	the input stream.
++ ----------------------------------------------------------------------------------------------*/
++-void GrSlotStream::AssertChunkMapsValid(GrSlotStream * psstrmOut)
+++void GrSlotStream::AssertChunkMapsValid(GrSlotStream * /*psstrmOut*/)
++ {
++ #ifdef _DEBUG
++ 	GrSlotStream * psstrmIn = this;
++@@ -1916,7 +1916,7 @@
++ 	Ensure that corresponding items in the streams of a positioning pass have matching
++ 	stream indices. The recipient is the output stream.
++ ----------------------------------------------------------------------------------------------*/
++-void GrSlotStream::AssertStreamIndicesValid(GrSlotStream * psstrmIn)
+++void GrSlotStream::AssertStreamIndicesValid(GrSlotStream * /*psstrmIn*/)
++ {
++ #ifdef _DEBUG
++ 	if (!GotIndexOffset())
++@@ -1940,7 +1940,7 @@
++ 	in the output stream. (Currently the compiler ensures this by making it an error
++ 	to write rules that don't do this.)
++ ----------------------------------------------------------------------------------------------*/
++-void GrSlotStream::AssertAttachmentsInOutput(int islotMin, int islotLim)
+++void GrSlotStream::AssertAttachmentsInOutput(int /*islotMin*/, int /*islotLim*/)
++ {
++ #ifdef _DEBUG
++ 	for (int islot = islotMin; islot < islotLim; islot++)
++@@ -2008,7 +2008,7 @@
++ 	Record the number of slots in the stream that are previous to the official start of the
++ 	segment.
++ ----------------------------------------------------------------------------------------------*/
++-void GrSlotStream::CalcIndexOffset(GrTableManager * ptman)
+++void GrSlotStream::CalcIndexOffset(GrTableManager * /*ptman*/)
++ {
++ 	if (GotIndexOffset())
++ 		return; // already figured it
++@@ -2343,9 +2343,10 @@
++ 			else if (pslotAfter)
++ 				pslot->Associate(pslotAfter);
++ 			else
+++			{
++ 				// Weird, but can happen with an empty segment.
++ 				Warn("No assocations");
++-
+++			}
++ //			Assert(pslot->m_vpslotAssoc.Size() > 0);
++ 			pslot->m_fNeutralAssocs = true;
++ 		}
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrSlotState.cpp.orig	2009-05-01 14:57:05.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrSlotState.cpp	2009-05-01 14:57:12.000000000 +0630
++@@ -261,7 +261,7 @@
++ 	root or attached leaf slots.
++ 	OBSOLETE
++ ----------------------------------------------------------------------------------------------*/
++-void GrSlotState::FixAttachmentTree(GrSlotState * pslotOld)
+++void GrSlotState::FixAttachmentTree(GrSlotState * /*pslotOld*/)
++ {
++ #if 0
++ 	pslotOld->m_vpslotAttLeaves.CopyTo(m_vpslotAttLeaves);
++@@ -524,13 +524,13 @@
++ 		GrSlotState * pslot;
++ 		if (HasComponents())
++ 		{
++-			for (int iComponent = 0; iComponent < m_cnCompPerLig; iComponent++)
+++			for (int iLigComponent = 0; iLigComponent < m_cnCompPerLig; iLigComponent++)
++ 			{
++-				pslot = CompRefSlot(iComponent);
+++				pslot = CompRefSlot(iLigComponent);
++ 				if (pslot)
++ 				{
++ 					Assert(PassModified() >= pslot->PassModified());
++-					pslot->AllComponentRefs(vichw, vicomp, iComponent);
+++					pslot->AllComponentRefs(vichw, vicomp, iLigComponent);
++ 				}
++ 			}
++ 		}
++@@ -1024,7 +1024,7 @@
++ 	NOTE: the caller is responsible to zap the cached positions of following glyphs
++ 	in the stream.
++ ----------------------------------------------------------------------------------------------*/
++-void GrSlotState::AttachToRoot(GrTableManager * ptman, GrSlotStream * psstrm,
+++void GrSlotState::AttachToRoot(GrTableManager * /*ptman*/, GrSlotStream * psstrm,
++ 	GrSlotState * pslotNewRoot)
++ {
++ 	GrSlotState * pslotOldRoot = (m_dislotRootFixed == 0) ?
++@@ -1129,7 +1129,7 @@
++ /*----------------------------------------------------------------------------------------------
++ 	Calculate the metrics for this node and all its leaf nodes.
++ ----------------------------------------------------------------------------------------------*/
++-void GrSlotState::CalcRootMetrics(GrTableManager * ptman, GrSlotStream * psstrm, int nLevel)
+++void GrSlotState::CalcRootMetrics(GrTableManager * /*ptman*/, GrSlotStream * psstrm, int nLevel)
++ {
++ 	for (size_t idislot = 0; idislot < m_vdislotAttLeaves.size(); idislot++)
++ 	{
++@@ -1263,7 +1263,7 @@
++ /*----------------------------------------------------------------------------------------------
++ 	Y-offsets of a single glyph relative to the previous advance position.
++ ----------------------------------------------------------------------------------------------*/
++-float GrSlotState::GlyphYOffset(GrSlotStream * psstrm)
+++float GrSlotState::GlyphYOffset(GrSlotStream * /*psstrm*/)
++ {
++ 	return m_ysOffsetY;
++ }
++--- misc/build/silgraphite-2.3.1/engine/src/segment/GrTableManager.cpp.orig	2009-05-01 15:00:39.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/GrTableManager.cpp	2009-05-01 15:03:11.000000000 +0630
++@@ -931,7 +931,7 @@
++ 	@param plbFound			- kind of line-break created
++ ----------------------------------------------------------------------------------------------*/
++ bool GrTableManager::Backtrack(int * pislotPrevBreak,
++-	LineBrk * plbMin, LineBrk lbMax, TrWsHandling twsh, bool fMoreText,
+++	LineBrk * plbMin, LineBrk lbMax, TrWsHandling twsh, bool /*fMoreText*/,
++ 	int ichwCallerBtLim, bool fEndLine,
++ 	LineBrk * plbFound)
++ {
++@@ -1343,7 +1343,7 @@
++ 	Calculate the associations, and record the output slots in the segment.
++ ----------------------------------------------------------------------------------------------*/
++ void GrTableManager::RecordAssocsAndOutput(Font * pfont,
++-	Segment * pseg, bool fWidthIsCharCount,
+++	Segment * pseg, bool /*fWidthIsCharCount*/,
++ 	TrWsHandling twsh, bool fParaRtl, int nDirDepth)
++ {
++ 	int cchwUnderlying = pseg->stopCharacter() - pseg->startCharacter();
++@@ -1377,7 +1377,7 @@
++ 	Calculate the underlying-to-surface associations and ligature mappings.
++ 	Assumes the arrays have been properly initialized.
++ ----------------------------------------------------------------------------------------------*/
++-void GrTableManager::CalculateAssociations(Segment * pseg, int csloutSurface)
+++void GrTableManager::CalculateAssociations(Segment * pseg, int /*csloutSurface*/)
++ {
++ 	GrSlotStream * psstrmFinal = OutputStream(m_cpass-1);
++ 
++@@ -2514,7 +2514,7 @@
++ 
++ 	for (size_t ipslot = 0; ipslot < vpslotAttached.size(); ipslot++)
++ 	{
++-		GrSlotState * pslot = vpslotAttached[ipslot];
+++		pslot = vpslotAttached[ipslot];
++ 		GrSlotState * pslotBase = pslot->Base(psstrm);
++ 		if (pslotBase->XPosition() == kNegInfinity || pslotBase->YPosition() == kNegInfinity)
++ 		{
++--- misc/build/silgraphite-2.3.1/engine/src/segment/Platform.cpp.orig	2009-05-01 15:05:31.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/Platform.cpp	2009-05-01 15:06:22.000000000 +0630
++@@ -103,7 +103,7 @@
++ {
++ 	// assumes NULL terminated strings
++ 	const utf16 *start = s;
++-	for (; *s; ++s);
+++	for (; *s; ++s) {};
++ 	
++ 	return s - start;
++ }
++--- misc/build/silgraphite-2.3.1/engine/src/segment/Segment.cpp.orig	2009-05-01 15:07:59.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/Segment.cpp	2009-05-01 15:14:01.000000000 +0630
++@@ -1178,7 +1178,7 @@
++ 	part of the segment.
++ ----------------------------------------------------------------------------------------------*/
++ float Segment::getRangeWidth(int ichMin, int ichLim,
++-	bool fStartLine, bool fEndLine, bool fSkipSpace)
+++	bool /*fStartLine*/, bool /*fEndLine*/, bool fSkipSpace)
++ {
++ 	if (m_dxsWidth < 0)
++ 	{
++@@ -1549,7 +1549,11 @@
++ void Segment::SetUpOutputArrays(Font * pfont, GrTableManager * ptman,
++ 	GrSlotStream * psstrmFinal,
++ 	int cchwInThisSeg, int csloutSurface, gid16 chwLB,
+++#ifdef NDEBUG
+++	TrWsHandling twsh, bool fParaRtl, int nDirDepth, bool /*fEmpty*/)
+++#else
++ 	TrWsHandling twsh, bool fParaRtl, int nDirDepth, bool fEmpty)
+++#endif
++ {
++ 	m_mFontEmUnits = EngineImpl()->GetFontEmUnits();
++ 
++@@ -1725,7 +1725,7 @@
++ 	Set up the data structures that represent the actual rendered glyphs for the new segment.
++ ----------------------------------------------------------------------------------------------*/
++ void Segment::SetUpGlyphInfo(GrTableManager * ptman, GrSlotStream * psstrmFinal,
++-	gid16 chwLB, int nDirDepth, int islotMin, int cslot)
+++	gid16 chwLB, int /*nDirDepth*/, int islotMin, int cslot)
++ {
++ 	//int paraDirLevel = (ptman->State()->ParaRightToLeft()) ? 1 : 0;
++ 
++@@ -1751,7 +1751,7 @@
++ 
++ 	m_isloutGinf0 = -1;
++ 	int iginf = 0;
++-	for (int islot = islotMin; islot < cslot; islot++)
+++	for (islot = islotMin; islot < cslot; islot++)
++ 	{
++ 		GrSlotState * pslot = psstrmFinal->SlotAt(islot);
++ 
++@@ -2351,7 +2351,7 @@
++ 	@param pfAfter			- return true if they clicked on trailing side; possibly NULL
++ ----------------------------------------------------------------------------------------------*/
++ int Segment::LogicalSurfaceToUnderlying(int islout, float xsOffset, float ysClick,
++-	float dxsGlyphWidth, float dysGlyphHeight, bool * pfAfter)
+++	float dxsGlyphWidth, float /*dysGlyphHeight*/, bool * pfAfter)
++ {
++ 	Assert(islout >= 0);
++ 	Assert(islout < m_cslout);
++@@ -2529,16 +2529,16 @@
++ 	else if (fBefore)
++ 	{
++ 		int isloutRet;
++-		int ichw = ichwSegOffset;
+++		int ichwTemp = ichwSegOffset;
++ 		//	If no association has been made, loop forward to the next slot
++ 		//	we are before. As a last resort, answer kPosInfinity, meaning we
++ 		//	aren't before anything.
++ 		do
++ 		{
++-			isloutRet = m_prgisloutBefore[ichw - m_ichwAssocsMin];
++-			do { ++ichw; }
++-			while (!GrCharStream::AtUnicodeCharBoundary(m_pgts, ichw));
++-		} while (isloutRet == kPosInfinity && ichw < m_ichwAssocsLim);
+++			isloutRet = m_prgisloutBefore[ichwTemp - m_ichwAssocsMin];
+++			do { ++ichwTemp; }
+++			while (!GrCharStream::AtUnicodeCharBoundary(m_pgts, ichwTemp));
+++		} while (isloutRet == kPosInfinity && ichwTemp < m_ichwAssocsLim);
++ 		return isloutRet;
++ 	}
++ 	else
++@@ -2748,7 +2748,11 @@
++ 	that root glyph as one of its roots.
++ 	OBSOLETE
++ ----------------------------------------------------------------------------------------------*/
+++#ifdef _DEBUG
++ void Segment::AssertValidClusters(GrSlotStream * psstrm)
+++#else
+++void Segment::AssertValidClusters(GrSlotStream * /*psstrm*/)
+++#endif
++ {
++ #ifdef _DEBUG
++ 	for (int islot = 0; islot < psstrm->WritePos(); islot++)
++--- misc/build/silgraphite-2.3.1/engine/src/segment/Segment.cpp.orig	2009-05-01 15:15:56.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/Segment.cpp	2009-05-01 15:17:41.000000000 +0630
++@@ -2160,7 +2160,7 @@
++ 	@param ichwUnder		- character index relative to the official beginning of the segment
++ 	@param islot			- processed glyph it maps to
++ ----------------------------------------------------------------------------------------------*/
++-void Segment::MarkSlotInPrevSeg(int ichwUnder, int islot)
+++void Segment::MarkSlotInPrevSeg(int ichwUnder, int /*islot*/)
++ {
++ 	if (ichwUnder >= m_ichwAssocsMin)
++ 		m_prgisloutBefore[ichwUnder - m_ichwAssocsMin] = kNegInfinity;
++@@ -2174,7 +2174,7 @@
++ 	@param ichwUnder		- character index relative to the official beginning of the segment
++ 	@param islot			- processed glyph it maps to
++ ----------------------------------------------------------------------------------------------*/
++-void Segment::MarkSlotInNextSeg(int ichwUnder, int islot)
+++void Segment::MarkSlotInNextSeg(int ichwUnder, int /*islot*/)
++ {
++ 	if (ichwUnder < m_ichwAssocsLim)
++ 		m_prgisloutAfter[ichwUnder - m_ichwAssocsMin] = kPosInfinity;
++@@ -2544,16 +2544,16 @@
++ 	else
++ 	{
++ 		int isloutRet;
++-		int ichw = ichwSegOffset;
+++		int ichwTemp = ichwSegOffset;
++ 		//	If no association has been made, loop backward to the previous slot
++ 		//	we are after. As a last resort, answer kNegInfinity, meaning we
++ 		//	aren't after anything.
++ 		do
++ 		{
++-			isloutRet = m_prgisloutAfter[ichw - m_ichwAssocsMin];
++-			do { --ichw; }
++-			while (!GrCharStream::AtUnicodeCharBoundary(m_pgts, ichw));
++-		} while (isloutRet == kNegInfinity && ichw >= 0);
+++			isloutRet = m_prgisloutAfter[ichwTemp - m_ichwAssocsMin];
+++			do { --ichwTemp; }
+++			while (!GrCharStream::AtUnicodeCharBoundary(m_pgts, ichwTemp));
+++		} while (isloutRet == kNegInfinity && ichwTemp >= 0);
++ 		return isloutRet;
++ 	}
++ 	Assert(false); // should never reach here
++--- misc/build/silgraphite-2.3.1/engine/src/segment/TransductionLog.cpp.orig	2009-05-01 15:21:39.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/segment/TransductionLog.cpp	2009-05-01 15:42:11.000000000 +0630
++@@ -175,7 +175,7 @@
++ 	Output a file showing a log of the transduction process and the resulting segment.
++ ----------------------------------------------------------------------------------------------*/
++ void GrTableManager::WriteXductnLog(std::ostream & strmOut,
++-	GrCharStream * pchstrm, Segment * psegRet,
+++	GrCharStream * pchstrm, Segment * /*psegRet*/,
++ 	int cbPrevSegDat, byte * pbPrevSegDat)
++ {
++ 	if (cbPrevSegDat == 0)
++@@ -416,8 +416,8 @@
++ 	the raw (UTF-16 or UTF-8) chars for display. To do this we get the raw characters
++ 	directly from the text source.
++ ----------------------------------------------------------------------------------------------*/
++-void GrCharStream::GetLogDataRaw(GrTableManager * ptman, int cchl, int cchrBackup,
++-	int cchrMaxRaw, int * prgchl,
+++void GrCharStream::GetLogDataRaw(GrTableManager * /*ptman*/, int cchl, int cchrBackup,
+++	int /*cchrMaxRaw*/, int * prgchl,
++ 	utf16 * prgchw2, utf16 * prgchw3, utf16 * prgchw4, utf16 * prgchw5, utf16 * prgchw6, 
++ 	int * prgcchr)
++ {
++@@ -441,7 +441,7 @@
++ 	case kutf8:
++ 		prgchsRunText8 = new utf8[cchrRange];
++ 		m_pgts->fetch(ichrMin, cchrRange, prgchsRunText8);
++-		for (int ichr = 0; ichr < cchrRange; ichr++)
+++		for (ichr = 0; ichr < cchrRange; ichr++)
++ 			prgchwRunText[ichr] = (utf16)prgchsRunText8[ichr];	// zero-extend into UTF-16 buffer
++ 		break;
++ 	case kutf16:
++@@ -634,7 +634,7 @@
++ 	m_pzpst->LogRulesFiredAndFailed(strmOut, psstrmIn);
++ }
++ 
++-void PassState::LogRulesFiredAndFailed(std::ostream & strmOut, GrSlotStream * psstrmIn)
+++void PassState::LogRulesFiredAndFailed(std::ostream & strmOut, GrSlotStream * /*psstrmIn*/)
++ {
++ 
++ 	strmOut << "PASS " << m_ipass << "\n\n" << "Rules matched: ";
++@@ -1193,7 +1193,7 @@
++ 	if (fAnyPseudos)
++ 	{
++ 		strmOut << "Actual glyphs: ";
++-		for (int islout = 0; islout < m_cslout; islout++)
+++		for (islout = 0; islout < m_cslout; islout++)
++ 		{
++ 			GrSlotOutput * psloutTmp = m_prgslout + islout;
++ 			if (psloutTmp->GlyphID() != psloutTmp->ActualGlyphForOutput(ptman))
++@@ -1319,7 +1319,7 @@
++ 	Write out the header lines for the slot contents.
++ ----------------------------------------------------------------------------------------------*/
++ void GrTableManager::LogSlotHeader(std::ostream & strmOut, int islotLim,
++-	int cspPerSlot, int cspLeading, int islotMin)
+++	int /*cspPerSlot*/, int cspLeading, int islotMin)
++ {
++ 	islotLim = min(islotLim, MAX_SLOTS);
++ 
++@@ -1721,7 +1721,7 @@
++ 
++ 	case kslatAttAtX:	// always do these in pairs
++ 	case kslatAttAtY:
++-		if (m_mAttachAtX != (pslotPrev ? pslotPrev->m_mAttachAtX : kNotYetSet) ||
+++		if (m_mAttachAtX != (pslotPrev ? pslotPrev->m_mAttachAtX : static_cast<short>(kNotYetSet)) ||
++ 			m_mAttachAtY != (pslotPrev ? pslotPrev->m_mAttachAtY : 0))
++ 		{
++ 			ptman->LogInTable(strmOut,
++@@ -1730,7 +1730,7 @@
++ 		}
++ 		break;
++ 	case kslatAttAtGpt:
++-		if (m_nAttachAtGpoint != (pslotPrev ? pslotPrev->m_nAttachAtGpoint : kNotYetSet))
+++		if (m_nAttachAtGpoint != (pslotPrev ? pslotPrev->m_nAttachAtGpoint : static_cast<short>(kNotYetSet)))
++ 		{
++ 			ptman->LogInTable(strmOut,
++ 				((m_nAttachAtGpoint == kGpointZero) ? 0 : m_nAttachAtGpoint));
++@@ -1750,7 +1750,7 @@
++ 
++ 	case kslatAttWithX:	// always do these in pairs
++ 	case kslatAttWithY:
++-		if (m_mAttachWithX != (pslotPrev ? pslotPrev->m_mAttachWithX : kNotYetSet) ||
+++		if (m_mAttachWithX != (pslotPrev ? pslotPrev->m_mAttachWithX : static_cast<short>(kNotYetSet)) ||
++ 			m_mAttachWithY != (pslotPrev ? pslotPrev->m_mAttachWithY : 0))
++ 		{
++ 			ptman->LogInTable(strmOut,
++@@ -1759,7 +1759,7 @@
++ 		}
++ 		break;
++ 	case kslatAttWithGpt:
++-		if (m_nAttachWithGpoint != (pslotPrev ? pslotPrev->m_nAttachWithGpoint : kNotYetSet))
+++		if (m_nAttachWithGpoint != (pslotPrev ? pslotPrev->m_nAttachWithGpoint : static_cast<short>(kNotYetSet)))
++ 		{
++ 			ptman->LogInTable(strmOut,
++ 				((m_nAttachWithGpoint == kGpointZero) ? 0 : m_nAttachWithGpoint));
++@@ -1786,14 +1786,14 @@
++ 		break;
++ 
++ 	case kslatBreak:
++-		if (m_lb != (pslotPrev ? pslotPrev->m_lb : kNotYetSet8))
+++		if (m_lb != (pslotPrev ? pslotPrev->m_lb : static_cast<sdata8>(kNotYetSet8)))
++ 		{
++ 			ptman->LogBreakWeightInTable(strmOut, m_lb);
++ 			return;
++ 		}
++ 		break;
++ 	case kslatDir:
++-		if (m_dirc != (pslotPrev ? pslotPrev->m_dirc : kNotYetSet8))
+++		if (m_dirc != (pslotPrev ? pslotPrev->m_dirc : static_cast<sdata8>(kNotYetSet8)))
++ 		{
++ 			ptman->LogDirCodeInTable(strmOut, m_dirc);
++ 			return;
++--- misc/build/silgraphite-2.3.1/engine/src/painter/SegmentPainter.cpp.orig	2009-05-01 16:35:12.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/src/painter/SegmentPainter.cpp	2009-05-02 13:59:49.000000000 +0630
++@@ -353,7 +353,7 @@
++ 	@param bOn				- true if we are turning on (ignored in this implementation)
++ ----------------------------------------------------------------------------------------------*/
++ bool SegmentPainter::drawSelectionRange(int ichwAnchor, int ichwEnd,
++-	float ydLineTop, float ydLineBottom, bool bOn)
+++	float ydLineTop, float ydLineBottom, bool /*bOn*/)
++ {
++ 	if (g_fDrawing)
++ 		return true;
++@@ -993,7 +993,7 @@
++ 								an I-beam (std selection)
++ ----------------------------------------------------------------------------------------------*/
++ void SegmentPainter::CalcOrDrawInsertionPoint(
++-	int ichwIP, bool fAssocPrev, bool bOn, bool fForceSplit,
+++	int ichwIP, bool fAssocPrev, bool /*bOn*/, bool fForceSplit,
++ 	Rect * prdPrimary, Rect * prdSecondary)
++ {
++ 	GrResult res = kresOk;
++@@ -1277,7 +1277,7 @@
++ 							if NULL, do the drawing
++ ----------------------------------------------------------------------------------------------*/
++ void SegmentPainter::InvertIBeam(float xs, float ysTop, float ysBottom,
++-	bool fAssocPrev, Rect * prdRet)
+++	bool /*fAssocPrev*/, Rect * prdRet)
++ {
++ 	float xd = ScaleXToDest(xs);
++ 	float ydTop = ScaleYToDest(ysTop);
++@@ -1675,7 +1675,7 @@
++ }
++ 
++ bool SegmentPainter::AtEdgeOfCluster(GrSlotOutput * psloutBase, int isloutBase,
++-	GrSlotOutput * pslout, int islout, bool fBefore)
+++	GrSlotOutput * /*pslout*/, int islout, bool fBefore)
++ {
++ 	//	Compare pslout to all the members of the cluster. If it is the minimum or maximum, it
++ 	//	is at an edge.
++@@ -1778,12 +1778,12 @@
++ 			}
++ 			for (icomp = 0; icomp < pslout->NumberOfComponents(); icomp++)
++ 			{
++-				for (int ichw = pslout->FirstUnderlyingComponent(icomp) ; 
++-					ichw <= pslout->LastUnderlyingComponent(icomp) ;
++-					ichw++)
+++				for (int ichwTemp = pslout->FirstUnderlyingComponent(icomp) ; 
+++					ichwTemp <= pslout->LastUnderlyingComponent(icomp) ;
+++					ichwTemp++)
++ 				{
++-					if (m_pseg->m_prgiComponent[ichw - m_pseg->m_ichwAssocsMin] == icomp)
++-						prgfAllSelected[ichw] = fAll;
+++					if (m_pseg->m_prgiComponent[ichwTemp - m_pseg->m_ichwAssocsMin] == icomp)
+++						prgfAllSelected[ichwTemp] = fAll;
++ 				}
++ 			}
++ 		}
++@@ -2304,7 +2304,11 @@
++ 	Assert that there are no overlaps among all the rectangles in the array, which should
++ 	be the case if AdjustRectsToNotOverlap is working properly.
++ ----------------------------------------------------------------------------------------------*/
+++#ifdef _DEBUG
++ void SegmentPainter::AssertNoOverlaps(std::vector<Rect> & vrect)
+++#else
+++void SegmentPainter::AssertNoOverlaps(std::vector<Rect> & /*vrect*/)
+++#endif
++ {
++ #ifdef _DEBUG
++ 	for (int irect1 = 0; irect1 < signed(vrect.size() - 1); irect1++)
++@@ -2452,7 +2456,11 @@
++ 	Assert that there are no overlaps among all the rectangles in the array, which should
++ 	be the case if AdjustRectsToNotOverlap is working properly.
++ ----------------------------------------------------------------------------------------------*/
+++#ifdef _DEBUG
++ void SegmentPainter::AssertNoOverlaps(std::vector<LineSeg> & vls)
+++#else
+++void SegmentPainter::AssertNoOverlaps(std::vector<LineSeg> & /*vls*/)
+++#endif
++ {
++ #ifdef _DEBUG
++ 	for (int ils1 = 0; ils1 < (int)vls.size() - 1; ils1++)
++@@ -2884,7 +2892,7 @@
++ 	{
++ 		if (icompNext != icompCurr)
++ 		{
++-			float xsHorizNext = (fIPOnRight) ? vxsRights[icompNext] : vxsLefts[icompNext];
+++			xsHorizNext = (fIPOnRight) ? vxsRights[icompNext] : vxsLefts[icompNext];
++ 			if (fMovingRight && xsHorizNext > xsHorizCurr)
++ 				break;
++ 			else if (!fMovingRight && xsHorizNext < xsHorizCurr)
++@@ -2996,7 +3004,7 @@
++ /*----------------------------------------------------------------------------------------------
++ 	Make sure the font is set to use the character properties required by this segment.
++ ----------------------------------------------------------------------------------------------*/
++-void SegmentPainter::SetFontProps(unsigned long clrFore, unsigned long clrBack)
+++void SegmentPainter::SetFontProps(unsigned long /*clrFore*/, unsigned long /*clrBack*/)
++ {
++ 	return;
++ }
++--- misc/build/silgraphite-2.3.1/engine/test/ProfileHarness/GrUtfTextSrc.h.orig	2009-05-02 14:06:23.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/test/ProfileHarness/GrUtfTextSrc.h	2009-05-02 14:09:58.000000000 +0630
++@@ -79,7 +79,7 @@
++   virtual size_t fetch(gr::toffset ichMin, size_t cch, gr::utf32 * prgchBuffer);
++   virtual size_t fetch(gr::toffset ichMin, size_t cch, gr::utf16 * prgchwBuffer);
++   virtual size_t fetch(gr::toffset ichMin, size_t cch, gr::utf8  * prgchsBuffer);
++-  virtual gr::GrResult getFaceName(int ich, unsigned int cchMax,
+++  virtual gr::GrResult getFaceName(int /*ich*/, unsigned int /*cchMax*/,
++     gr::utf16 * prgchFaceName, unsigned int * pcchLen) 
++   {
++     prgchFaceName[0] = 0;
++@@ -92,12 +92,12 @@
++   virtual bool getItalic(gr::toffset ich);
++   virtual bool getRightToLeft(gr::toffset ich);
++   virtual unsigned int getDirectionDepth(gr::toffset ich);
++-  virtual float getVerticalOffset(gr::toffset ich) { return 0;};
+++  virtual float getVerticalOffset(gr::toffset /*ich*/) { return 0;};
++   virtual gr::isocode getLanguage(gr::toffset ich);
++ 
++   virtual std::pair<gr::toffset, gr::toffset> propertyRange(gr::toffset ich);
++   virtual size_t getFontFeatures(gr::toffset ich, gr::FeatureSetting * prgfset);
++-  virtual bool sameSegment(gr::toffset ich1, gr::toffset ich2) { return true; };
+++  virtual bool sameSegment(gr::toffset /*ich1*/, gr::toffset /*ich2*/) { return true; };
++ 
++ protected:
++   bool checkBuffer8();
++@@ -129,11 +129,11 @@
++   virtual void getColors(gr::toffset ich, int * pclrFore, int * pclrBack);
++ 
++   // Shouldn't be here!  
++-  virtual gr::GrResult Fetch(int ichMin, int ichLim, gr::utf16 * prgchBuf) { return gr::kresNotImpl; };
++-  virtual gr::GrResult get_Length(int * pcch) { return gr::kresNotImpl; };
++-  virtual gr::GrResult GetFontVariations(int ich,
++-    wchar_t * prgchFontVar, int ichMax, int * pich,
++-    int * pichMin, int * pichLim) { return gr::kresNotImpl; };
+++  virtual gr::GrResult Fetch(int /*ichMin*/, int /*ichLim*/, gr::utf16 * /*prgchBuf*/) { return gr::kresNotImpl; };
+++  virtual gr::GrResult get_Length(int * /*pcch*/) { return gr::kresNotImpl; };
+++  virtual gr::GrResult GetFontVariations(int /*ich*/,
+++    wchar_t * /*prgchFontVar*/, int /*ichMax*/, int * /*pich*/,
+++    int * /*pichMin*/, int * /*pichLim*/) { return gr::kresNotImpl; };
++ 
++ };
++ 
++--- misc/build/silgraphite-2.3.1/engine/test/ProfileHarness/GrUtfTextSrc.cpp.orig	2009-05-02 14:02:53.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/test/ProfileHarness/GrUtfTextSrc.cpp	2009-05-02 14:05:38.000000000 +0630
++@@ -210,12 +210,12 @@
++ }
++ 
++ 
++-bool GrUtfTextSrc::getRightToLeft(gr::toffset ich)
+++bool GrUtfTextSrc::getRightToLeft(gr::toffset /*ich*/)
++ {
++ 	return mRtl; // assumes src only contains one direction
++ }
++ 
++-unsigned int GrUtfTextSrc::getDirectionDepth(gr::toffset ich)
+++unsigned int GrUtfTextSrc::getDirectionDepth(gr::toffset /*ich*/)
++ {
++ 	return (mRtl) ? 1 : 0; // TBD
++ }
++@@ -254,7 +254,7 @@
++ 	return range;
++ }
++ 	
++-size_t GrUtfTextSrc::getFontFeatures(gr::toffset ich, gr::FeatureSetting * prgfset)
+++size_t GrUtfTextSrc::getFontFeatures(gr::toffset /*ich*/, gr::FeatureSetting * /*prgfset*/)
++ {
++ 	return 0;
++ }
++@@ -277,14 +277,14 @@
++ 
++ // these should be called I hope
++ float
++-GrUtfTextSrc::getFontSize(gr::toffset ich)
+++GrUtfTextSrc::getFontSize(gr::toffset /*ich*/)
++ {
++ 	assert(mFont);
++ 	return mPointSize;
++ }
++ 
++ bool
++-GrUtfTextSrc::getBold(gr::toffset ich)
+++GrUtfTextSrc::getBold(gr::toffset /*ich*/)
++ {
++ 	assert(mFont);
++ //	NS_ASSERTION(false, "unexpected call to getBold");
++@@ -293,7 +293,7 @@
++ }
++ 
++ bool
++-GrUtfTextSrc::getItalic(gr::toffset ich)
+++GrUtfTextSrc::getItalic(gr::toffset /*ich*/)
++ {
++ 	assert(mFont);
++ 	//NS_ASSERTION(false, "unexpected call to getItalic");
++@@ -301,7 +301,7 @@
++ 	return mFont->italic();
++ }
++ 
++-gr::isocode GrUtfTextSrc::getLanguage(gr::toffset ich)
+++gr::isocode GrUtfTextSrc::getLanguage(gr::toffset /*ich*/)
++ {
++   gr::isocode unknown;
++   std::fill_n(unknown.rgch, 4, '\0');
++--- misc/build/silgraphite-2.3.1/engine/test/ProfileHarness/ProfileHarness.cpp.orig	2009-05-02 14:12:29.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/test/ProfileHarness/ProfileHarness.cpp	2009-05-02 14:14:17.000000000 +0630
++@@ -39,14 +39,14 @@
++ typedef std::pair< gr::GlyphIterator, gr::GlyphIterator > GlyphRange;
++ 
++ #ifndef HAVE_STRTOF
++-float strtof(char * text, char ** ignore)
+++float strtof(char * text, char ** /*ignore*/)
++ {
++   return static_cast<float>(atof(text));
++ }
++ #endif
++ 
++ #ifndef HAVE_STRTOL
++-long strtol(char * text, char ** ignore)
+++long strtol(char * text, char ** /*ignore*/)
++ {
++   return atol(text);
++ }
++--- misc/build/silgraphite-2.3.1/engine/test/RegressionTest/RegressionTest.cpp.orig	2009-05-02 14:42:39.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/test/RegressionTest/RegressionTest.cpp	2009-05-02 14:43:09.000000000 +0630
++@@ -675,7 +675,7 @@
++ 	OutputErrorAux(ptcase, strErr, i, true, valueFound, valueExpected);
++ }
++ 
++-void OutputErrorAux(TestCase * ptcase, std::string strErr, int i,
+++void OutputErrorAux(TestCase * /*ptcase*/, std::string strErr, int i,
++ 	bool showValues, int valueFound, int valueExpected)
++ {
++ //	if (g_debugMode)
++--- misc/build/silgraphite-2.3.1/engine/test/RegressionTest/RtTextSrc.h.orig	2009-05-02 14:19:47.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/test/RegressionTest/RtTextSrc.h	2009-05-02 14:37:25.000000000 +0630
++@@ -44,18 +44,18 @@
++ 		}
++ 	}
++ 
++-	virtual size_t getFontFeatures(toffset ich, FeatureSetting * prgfset)
+++	virtual size_t getFontFeatures(toffset /*ich*/, FeatureSetting * prgfset)
++ 	{
++ 		// Note: size of prgfset buffer = gr::kMaxFeatures = 64
++ 		std::copy(m_fset, m_fset + MAXFEAT, prgfset);
++ 		return m_cFeats;
++ 	}
++ 
++-	virtual bool getRightToLeft(toffset ich)
+++	virtual bool getRightToLeft(toffset /*ich*/)
++ 	{
++ 		return m_fRtl;
++ 	}
++-	virtual unsigned int getDirectionDepth(toffset ich)
+++	virtual unsigned int getDirectionDepth(toffset /*ich*/)
++ 	{
++ 		return ((m_fRtl == 1) ? 1 : 0);
++ 	}
++--- misc/build/silgraphite-2.3.1/engine/test/RegressionTest/SimpleTextSrc.h.orig	2009-05-02 14:17:10.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/test/RegressionTest/SimpleTextSrc.h	2009-05-02 14:19:14.000000000 +0630
++@@ -59,12 +59,12 @@
++ 	{
++ 		return m_cchLength;
++ 	}
++-	virtual size_t fetch(toffset ichMin, size_t cch, utf32 * prgchBuffer)
+++	virtual size_t fetch(toffset /*ichMin*/, size_t /*cch*/, utf32 * /*prgchBuffer*/)
++ 	{
++ 		throw;
++ 	}
++ 	virtual size_t fetch(toffset ichMin, size_t cch, gr::utf16 * prgchwBuffer);
++-	virtual size_t fetch(toffset ichMin, size_t cch, utf8  * prgchsBuffer)
+++	virtual size_t fetch(toffset /*ichMin*/, size_t /*cch*/, utf8  * /*prgchsBuffer*/)
++ 	{
++ 		throw;
++ 	};
++@@ -73,14 +73,14 @@
++ 	virtual unsigned int getDirectionDepth(toffset ich);
++ 	virtual float getVerticalOffset(toffset ich);
++ 
++-	virtual isocode getLanguage(toffset ich)
+++	virtual isocode getLanguage(toffset /*ich*/)
++ 	{
++ 		isocode ret;
++ 		ret.rgch[0] = 'e'; ret.rgch[1] = 'n'; ret.rgch[2] = 0; ret.rgch[3] = 0;
++ 		return ret;
++ 	}
++ 
++-	virtual std::pair<toffset, toffset> propertyRange(toffset ich)
+++	virtual std::pair<toffset, toffset> propertyRange(toffset /*ich*/)
++ 	{
++ 		std::pair<toffset, toffset> pairRet;
++ 		pairRet.first = 0;
++@@ -88,16 +88,16 @@
++ 		return pairRet;
++ 	}
++ 
++-	virtual size_t getFontFeatures(toffset ich, FeatureSetting * prgfset)
+++	virtual size_t getFontFeatures(toffset /*ich*/, FeatureSetting * /*prgfset*/)
++ 	{
++ 		return 0; // no features in this simple implementation
++ 	}
++-	virtual bool sameSegment(toffset ich1, toffset ich2)
+++	virtual bool sameSegment(toffset /*ich1*/, toffset /*ich2*/)
++ 	{
++ 		return true;
++ 	}
++ 
++-	virtual void getColors(toffset ich, int * pclrFore, int * pclrBack)
+++	virtual void getColors(toffset /*ich*/, int * pclrFore, int * pclrBack)
++ 	{
++ 		*pclrFore = kclrBlack;
++ 		*pclrBack = kclrTransparent;
++--- misc/build/silgraphite-2.3.1/engine/test/RegressionTest/SimpleTextSrc.cpp.orig	2009-05-02 14:50:27.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/test/RegressionTest/SimpleTextSrc.cpp	2009-05-02 14:50:55.000000000 +0630
++@@ -70,7 +70,7 @@
++ /*----------------------------------------------------------------------------------------------
++ 	Return true if the text uses a right-to-left writing system.
++ ----------------------------------------------------------------------------------------------*/
++-bool SimpleTextSrc::getRightToLeft(toffset ich)
+++bool SimpleTextSrc::getRightToLeft(toffset /*ich*/)
++ {
++ 	return false;
++ }
++@@ -78,7 +78,7 @@
++ /*----------------------------------------------------------------------------------------------
++ 	Return the depth of embedding of the writing system.
++ ----------------------------------------------------------------------------------------------*/
++-unsigned int SimpleTextSrc::getDirectionDepth(toffset ich)
+++unsigned int SimpleTextSrc::getDirectionDepth(toffset /*ich*/)
++ {
++ 	return 0;
++ }
++@@ -87,7 +87,7 @@
++ 	Return the vertical offset of the text. This simple implementation provides no
++ 	vertical offset.
++ ----------------------------------------------------------------------------------------------*/
++-float SimpleTextSrc::getVerticalOffset(toffset ich)
+++float SimpleTextSrc::getVerticalOffset(toffset /*ich*/)
++ {
++ 	return 0;
++ }
++--- misc/build/silgraphite-2.3.1/engine/test/RegressionTest/GrJustifier.cpp.orig	2009-05-02 14:52:36.000000000 +0630
+++++ misc/build/silgraphite-2.3.1/engine/test/RegressionTest/GrJustifier.cpp	2009-05-02 14:54:19.000000000 +0630
++@@ -327,7 +327,7 @@
++ 					&dxStretchAchieved);
++ 				for (int iiiGlyph = 0; iiiGlyph < cStretchable; iiiGlyph++)
++ 				{
++-					int iiGlyph = viiGlyphsRem[iiiGlyph];
+++					iiGlyph = viiGlyphsRem[iiiGlyph];
++ 					vdxStretchLeft[iiGlyph] = vdxStretchRem[iiiGlyph];
++ 					vdxWidth[iiGlyph] = vdxWidthRem[iiiGlyph];
++ 				}
+Index: graphite/makefile.mk
+===================================================================
+--- graphite/makefile.mk	(.../tags/DEV300_m49)	(Revision 0)
++++ graphite/makefile.mk	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,173 @@
++#*************************************************************************
++#
++#   $RCSfile: graphite-makefile-mk.diff,v $
++#
++#   $Revision: 1.11 $
++#
++#   last change: $Author: rodo $ $Date: 2006/01/03 17:58:01 $
++#
++#   The Contents of this file are made available subject to the terms of
++#   either of the following licenses
++#
++#          - GNU Lesser General Public License Version 2.1
++#          - Sun Industry Standards Source License Version 1.1
++#
++#   Sun Microsystems Inc., October, 2000
++#
++#   GNU Lesser General Public License Version 2.1
++#   =============================================
++#   Copyright 2000 by Sun Microsystems, Inc.
++#   901 San Antonio Road, Palo Alto, CA 94303, USA
++#
++#   This library is free software; you can redistribute it and/or
++#   modify it under the terms of the GNU Lesser General Public
++#   License version 2.1, as published by the Free Software Foundation.
++#
++#   This library is distributed in the hope that it will be useful,
++#   but WITHOUT ANY WARRANTY; without even the implied warranty of
++#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++#   Lesser General Public License for more details.
++#
++#   You should have received a copy of the GNU Lesser General Public
++#   License along with this library; if not, write to the Free Software
++#   Foundation, Inc., 59 Temple Place, Suite 330, Boston,
++#   MA  02111-1307  USA
++#
++#
++#   Sun Industry Standards Source License Version 1.1
++#   =================================================
++#   The contents of this file are subject to the Sun Industry Standards
++#   Source License Version 1.1 (the "License"); You may not use this file
++#   except in compliance with the License. You may obtain a copy of the
++#   License at http://www.openoffice.org/license.html.
++#
++#   Software provided under this License is provided on an "AS IS" basis,
++#   WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
++#   WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
++#   MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
++#   See the License for the specific provisions governing your rights and
++#   obligations concerning the Software.
++#
++#   The Initial Developer of the Original Code is: Sun Microsystems, Inc.
++#
++#   Copyright: 2000 by Sun Microsystems, Inc.
++#
++#   All Rights Reserved.
++#
++#   Contributor(s): _______________________________________
++#
++#
++#
++#*************************************************************************
++
++PRJ=.
++
++PRJNAME=graphite
++TARGET=so_graphite
++
++# --- Settings -----------------------------------------------------
++
++.INCLUDE :	settings.mk
++
++# --- Files --------------------------------------------------------
++
++TARFILE_NAME=silgraphite-2.3.1
++PATCH_FILES=graphite-2.3.1.patch
++
++#.IF "$(OS)"=="WNT" && "$(COM)"!="GCC"
++#CONFIGURE_DIR=win32
++#.ELSE
++#CONFIGURE_DIR=engine
++#.ENDIF
++
++CONFIGURE_DIR=engine
++
++.IF "$(COM)"=="MSC"
++.IF "$(COMEX)"=="10"
++VCNUM=7
++.ELSE
++VCNUM=8
++.ENDIF
++# make use of stlport headerfiles
++EXT_USE_STLPORT=TRUE
++BUILD_ACTION=nmake
++.IF "$(debug)"=="true"
++BUILD_FLAGS= "CFG=DEBUG" "MLIB=MD" /F makefile.vc$(VCNUM) dll
++.ELSE
++BUILD_FLAGS="MLIB=MD" /F makefile.vc$(VCNUM) dll
++.ENDIF
++.ENDIF
++
++.IF "$(COM)"=="GCC"
++
++# Does linux want --disable-shared?
++.IF "$(debug)"=="true"
++GR_CONFIGURE_FLAGS= --enable-debug=yes --disable-final --enable-static --disable-shared
++.ELSE
++GR_CONFIGURE_FLAGS= --enable-final=yes --enable-static --disable-shared
++.ENDIF
++EXTRA_GR_CXX_FLAGS=-fPIC
++
++.IF "$(USE_SYSTEM_STL)"!="YES"
++EXTRA_GR_LD_FLAGS=-lstlport_gcc
++GR_LIB_PATH=LD_LIBRARY_PATH=$(SOLARVERSION)/$(INPATH)/lib
++.ELSE
++GR_LIB_PATH=
++.ENDIF
++
++# don't use SOLARLIB for LDFLAGS because it pulls in system graphite so build will fail
++# 
++CONFIGURE_ACTION=bash -c 'CXXFLAGS="$(INCLUDE) $(CFLAGSCXX) $(CFLAGSCOBJ) $(CDEFS) $(CDEFSOBJ) $(SOLARINC) $(LFS_CFLAGS) $(EXTRA_GR_CXX_FLAGS)" $(GR_LIB_PATH) LDFLAGS="-L$(SOLARVERSION)/$(INPATH)/lib $(EXTRA_GR_LD_FLAGS)" ./configure $(GR_CONFIGURE_FLAGS)'
++.ENDIF
++
++BUILD_DIR=$(CONFIGURE_DIR)
++
++.IF "$(OS)"=="WNT" && "$(COM)"!="GCC"
++#OUT2LIB=win32$/bin.msvc$/*.lib
++.IF "$(debug)"=="true"
++OUT2LIB=engine$/debug$/*.lib
++.ELSE
++OUT2LIB=engine$/release$/*.lib
++.ENDIF
++.ELSE
++OUT2LIB=engine$/src$/.libs$/libgraphite*.a
++.ENDIF
++
++.IF "$(COM)"=="GCC"
++BUILD_ACTION=$(GNUMAKE) -j$(EXTMAXPROCESS)
++.ENDIF
++
++.IF "$(OS)"=="MACOSX"
++OUT2LIB+=src$/.libs$/libgraphite.*.dylib
++.ELSE
++.IF "$(OS)"=="WNT"
++#OUT2LIB+=engine$/src$/.libs$/libgraphite*.dll
++.IF "$(debug)"=="true"
++OUT2BIN= \
++    engine$/debug$/*.dll \
++    engine$/debug$/*.pdb
++.ELSE
++OUT2BIN= \
++    engine$/release$/*.dll
++#    engine$/release$/*.pdb
++.ENDIF
++.ELSE
++#OUT2LIB+=engine$/src$/.libs$/libgraphite.so.*.*.*
++.ENDIF
++.ENDIF
++
++
++OUTDIR2INC= \
++	engine$/include$/graphite
++
++.IF "$(OS)"=="WNT"
++OUT2INC=wrappers$/win32$/WinFont.h
++.ENDIF
++
++# --- Targets ------------------------------------------------------
++
++
++.INCLUDE :	set_ext.mk
++.INCLUDE :	target.mk
++.INCLUDE :	tg_ext.mk
++
+Index: graphite/download/Readme.txt
+===================================================================
+--- graphite/download/Readme.txt	(.../tags/DEV300_m49)	(Revision 0)
++++ graphite/download/Readme.txt	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,15 @@
++The Graphite library is free software; you can redistribute it and/or modify
++    it under the terms of either:
++
++	a) the Common Public License as published by the "Agreement
++         Steward" for that license (currently IBM); either version 0.5
++         of the License, or (at your option) any later version,
++
++    or
++
++	b) the GNU Lesser General Public License as published by the
++         Free Software Foundation; either version 2.1 of License, or
++         (at your option) any later version.
++
++Download source tarball of silgraphite-version.tar.gz from http://sf.net/projects/silgraphite
++Place the downloaded tar ball in this directory.
+Index: graphite/download/silgraphite-2.3.1.tar.gz
+===================================================================
+Kann nicht anzeigen: Dateityp ist als binär angegeben.
+svn:mime-type = application/octet-stream
+
+Eigenschaftsänderungen: graphite/download/silgraphite-2.3.1.tar.gz
+___________________________________________________________________
+Hinzugefügt: svn:mime-type
+   + application/octet-stream
+
+Index: graphite/prj/build.lst
+===================================================================
+--- graphite/prj/build.lst	(.../tags/DEV300_m49)	(Revision 0)
++++ graphite/prj/build.lst	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,3 @@
++gr	graphite	:	stlport solenv NULL
++gr	graphite		usr1	-	all	gr_mkout NULL
++gr	graphite		nmake	-	all	gr_graphite NULL
+Index: graphite/prj/d.lst
+===================================================================
+--- graphite/prj/d.lst	(.../tags/DEV300_m49)	(Revision 0)
++++ graphite/prj/d.lst	(.../cws/graphite01)	(Revision 273505)
+@@ -0,0 +1,15 @@
++mkdir: %_DEST%\inc%_EXT%\graphite
++..\%__SRC%\inc\graphite\*.h %_DEST%\inc%_EXT%\graphite\*.h
++..\%__SRC%\inc\WinFont.h %_DEST%\inc%_EXT%\graphite\WinFont.h
++
++..\%__SRC%\lib\*.so.* %_DEST%\lib%_EXT%\*.so.*
++..\%__SRC%\lib\*.dylib %_DEST%\lib%_EXT%\*.dylib
++..\%__SRC%\lib\*.a %_DEST%\lib%_EXT%\*.a
++..\%__SRC%\lib\*.lib %_DEST%\lib%_EXT%\*.lib
++..\%__SRC%\bin\*.dll %_DEST%\bin%_EXT%\*.dll
++..\%__SRC%\bin\*.pdb %_DEST%\bin%_EXT%\*.pdb
++..\%__SRC%\lib\graphite.lib %_DEST%\lib%_EXT%\graphite.lib
++
++linklib: libgraphite.so.*.*.*
++linklib: libgraphite.dylib.*.*.*
++#linklib: graphite.*
+
+Eigenschaftsänderungen: graphite
+___________________________________________________________________
+Hinzugefügt: svn:ignore
+   + unxlngs390x unxlngi6 unxlngmips unxirxm3 unxfbsd.pro unxols4 unxirxm3.pro unxsogi.pro unxlngp unxsoli4.pro common.pro unxlngppc64.pro unxubit8.pro wntmsci12 unxlngx6.pro unxsogi unxlngr unxols4.pro unxsols4 unxfbsdx unxhpxr unxlngs.pro unxsoli4 unxbsds.pro unxaixp.pro unxlngx6 unxlngppc4 unxfbsd unxbsds unxmacxp unxbsdi2 common unxlngr.pro unxirgm unxbsdi.pro unxbsda.pro unxirgm.pro unxsolu4.pro unxlngppc.pro unxhpgr.pro unxlngs3904 unxaixp unxsolu4 unxlngm68k unxlnga unxmacxi.pro unxirxm unxlngppc4.pro unxsols4.pro unxfbsdi unxmacxi wntmsci12.pro unxlngs390x.pro unxlngmips.pro unxhpgr unxirxm.pro unxmacxp.pro unxlngppc unxfbsdx.pro unxlnxi.pro unxlnxi unxubit8 unxhpxr.pro unxlngppc64 unxfbsdi.pro unxlngs3904.pro unxlngi6.pro unxlngp.pro unxlngs unxbsdi2.pro unxbsdi unxlnga.pro unxbsda unxsogs.pro unxsogs unxlngm68k.pro 
+
+
+Index: scp2/source/ooo/shortcut_ooo.scp
+===================================================================
+--- scp2/source/ooo/shortcut_ooo.scp	(.../tags/DEV300_m49)	(Revision 273505)
++++ scp2/source/ooo/shortcut_ooo.scp	(.../cws/graphite01)	(Revision 273505)
+@@ -62,6 +62,28 @@
+ End
+ 
+ #endif
++
++Shortcut gid_Shortcut_Lib_Graphite_0
++    FileID = gid_File_Lib_Graphite;
++    Dir = gid_Dir_Program;
++    Name = STRING(CONCAT2(libgraphite,UNXSUFFIX));
++    Styles = (NETWORK,RELATIVE);
++End
++
++Shortcut gid_Shortcut_Lib_Graphite_1
++    FileID = gid_File_Lib_Graphite;
++    Dir = gid_Dir_Program;
++    Name = STRING(CONCAT4(libgraphite,UNXSUFFIX,.,3));
++    Styles = (NETWORK,RELATIVE);
++End
++
++Shortcut gid_Shortcut_Lib_Graphite_2
++    FileID = gid_File_Lib_Graphite;
++    Dir = gid_Dir_Program;
++    Name = STRING(CONCAT4(libgraphite,UNXSUFFIX,.,3.0));
++    Styles = (NETWORK,RELATIVE);
++End
++
+ #endif
+ 
+ #ifdef MACOSX
+
+Eigenschaftsänderungen: solenv/bin/modules/Cws.pm
+___________________________________________________________________
+Hinzugefügt: svn:mergeinfo
+   Zusammengeführt /trunk/solenv/bin/modules/Cws.pm:r263289-272290
+   Zusammengeführt /cws/appleremote01/solenv/bin/modules/Cws.pm:r261927-262777
+   Zusammengeführt /cws/basebmpunittestfix/solenv/bin/modules/Cws.pm:r262088-262763
+   Zusammengeführt /cws/svnl10nmerge/solenv/bin/modules/Cws.pm:r261961-262281
+   Zusammengeführt /cws/hr54/solenv/bin/modules/Cws.pm:r262088-262569
+   Zusammengeführt /cws/hr55/solenv/bin/modules/Cws.pm:r262621-262856
+   Zusammengeführt /tags/DEV300_m41/solenv/bin/modules/Cws.pm:r267171-267231
+   Zusammengeführt /tags/DEV300_m32/solenv/bin/modules/Cws.pm:r261926-261960
+   Zusammengeführt /cws/bmpsum1/solenv/bin/modules/Cws.pm:r262621-262796
+   Zusammengeführt /cws/sb97/solenv/bin/modules/Cws.pm:r262088-262770
+   Zusammengeführt /tags/DEV300_m43/solenv/bin/modules/Cws.pm:r269297-269740
+   Zusammengeführt /cws/sb99/solenv/bin/modules/Cws.pm:r262088-262817
+   Zusammengeführt /cws/impresszoom/solenv/bin/modules/Cws.pm:r261927-262795
+   Zusammengeführt /cws/cli001/solenv/bin/modules/Cws.pm:r262088-262280
+   Zusammengeführt /tags/DEV300_m46/solenv/bin/modules/Cws.pm:r270723-270963
+   Zusammengeführt /cws/cli002/solenv/bin/modules/Cws.pm:r262088-262753
+   Zusammengeführt /cws/cli003/solenv/bin/modules/Cws.pm:r262621-262819
+   Zusammengeführt /cws/rt33/solenv/bin/modules/Cws.pm:r262088-262231
+   Zusammengeführt /cws/odbmacros3/solenv/bin/modules/Cws.pm:r261929-262238
+   Zusammengeführt /tags/DEV300_m49/solenv/bin/modules/Cws.pm:r272291-272475
+   Zusammengeführt /cws/svnignoreoutpaths/solenv/bin/modules/Cws.pm:r262088-262759
+   Zusammengeführt /cws/vcl95/solenv/bin/modules/Cws.pm:r261927-262773
+   Zusammengeführt /cws/qadocinfo/solenv/bin/modules/Cws.pm:r262621-263278
+   Zusammengeführt /cws/aw057/solenv/bin/modules/Cws.pm:r262017-262273
+   Zusammengeführt /cws/os120/solenv/bin/modules/Cws.pm:r261927-262782
+
+
+Eigenschaftsänderungen: solenv/bin/modules/CwsConfig.pm
+___________________________________________________________________
+Hinzugefügt: svn:mergeinfo
+   Zusammengeführt /cws/svnl10nmerge/solenv/bin/modules/CwsConfig.pm:r261961-262281
+   Zusammengeführt /cws/hr54/solenv/bin/modules/CwsConfig.pm:r262088-262569
+   Zusammengeführt /cws/hr55/solenv/bin/modules/CwsConfig.pm:r262621-262856
+   Zusammengeführt /tags/DEV300_m41/solenv/bin/modules/CwsConfig.pm:r267171-267231
+   Zusammengeführt /tags/DEV300_m32/solenv/bin/modules/CwsConfig.pm:r261926-261960
+   Zusammengeführt /cws/bmpsum1/solenv/bin/modules/CwsConfig.pm:r262621-262796
+   Zusammengeführt /cws/sb97/solenv/bin/modules/CwsConfig.pm:r262088-262770
+   Zusammengeführt /tags/DEV300_m43/solenv/bin/modules/CwsConfig.pm:r269297-269740
+   Zusammengeführt /cws/sb99/solenv/bin/modules/CwsConfig.pm:r262088-262817
+   Zusammengeführt /cws/impresszoom/solenv/bin/modules/CwsConfig.pm:r261927-262795
+   Zusammengeführt /cws/cli001/solenv/bin/modules/CwsConfig.pm:r262088-262280
+   Zusammengeführt /tags/DEV300_m46/solenv/bin/modules/CwsConfig.pm:r270723-270963
+   Zusammengeführt /cws/cli002/solenv/bin/modules/CwsConfig.pm:r262088-262753
+   Zusammengeführt /cws/cli003/solenv/bin/modules/CwsConfig.pm:r262621-262819
+   Zusammengeführt /cws/rt33/solenv/bin/modules/CwsConfig.pm:r262088-262231
+   Zusammengeführt /cws/odbmacros3/solenv/bin/modules/CwsConfig.pm:r261929-262238
+   Zusammengeführt /tags/DEV300_m49/solenv/bin/modules/CwsConfig.pm:r272291-272475
+   Zusammengeführt /cws/svnignoreoutpaths/solenv/bin/modules/CwsConfig.pm:r262088-262759
+   Zusammengeführt /cws/vcl95/solenv/bin/modules/CwsConfig.pm:r261927-262773
+   Zusammengeführt /cws/qadocinfo/solenv/bin/modules/CwsConfig.pm:r262621-263278
+   Zusammengeführt /cws/aw057/solenv/bin/modules/CwsConfig.pm:r262017-262273
+   Zusammengeführt /cws/os120/solenv/bin/modules/CwsConfig.pm:r261927-262782
+   Zusammengeführt /trunk/solenv/bin/modules/CwsConfig.pm:r263289-272290
+   Zusammengeführt /cws/appleremote01/solenv/bin/modules/CwsConfig.pm:r261927-262777
+   Zusammengeführt /cws/basebmpunittestfix/solenv/bin/modules/CwsConfig.pm:r262088-262763
+
+Index: set_soenv.in
+===================================================================
+--- set_soenv.in	(.../tags/DEV300_m49)	(Revision 273505)
++++ set_soenv.in	(.../cws/graphite01)	(Revision 273505)
+@@ -1816,6 +1816,10 @@
+ ToFile( "ENABLE_DIRECTX",    "@ENABLE_DIRECTX@",    "e" );
+ ToFile( "ENABLE_LAYOUT",     "@ENABLE_LAYOUT@",     "e" );
+ ToFile( "ENABLE_PCH",        "@ENABLE_PCH@",       "e" );
++ToFile( "ENABLE_GRAPHITE",   "@ENABLE_GRAPHITE@",   "e");
++ToFile( "SYSTEM_GRAPHITE",   "@SYSTEM_GRAPHITE@",   "e");
++ToFile( "GRAPHITE_LIBS",     "@GRAPHITE_LIBS@",     "e");
++ToFile( "GRAPHITE_CFLAGS",   "@GRAPHITE_CFLAGS@",   "e");
+ ToFile( "VC_STANDARD",       "@VC_STANDARD@",      "e" );
+ ToFile( "WITH_GPC",          "@WITH_GPC@",         "e" );
+ ToFile( "WITH_MYSPELL_DICTS","@WITH_MYSPELL_DICTS@","e");
+Index: canvas/source/directx/makefile.mk
+===================================================================
+--- canvas/source/directx/makefile.mk	(.../tags/DEV300_m49)	(Revision 273505)
++++ canvas/source/directx/makefile.mk	(.../cws/graphite01)	(Revision 273505)
+@@ -96,7 +96,7 @@
+ 	$(SLO)$/dx_canvas.obj
+ GDIPLUS_SLOFILES += $(SHARED_SLOFILES)
+ 
+-STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(VCLLIB) $(TOOLSLIB) $(UNOTOOLSLIB)
++STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(VCLLIB) $(TOOLSLIB) $(UNOTOOLSLIB) $(I18NISOLANGLIB)
+ 
+ 
+ ########################################################
+@@ -194,7 +194,7 @@
+ SHL3TARGET=$(TARGET3).uno
+ 
+ # Links import libraries.
+-SHL3STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(VCLLIB) $(TOOLSLIB) $(UNOTOOLSLIB)
++SHL3STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(VCLLIB) $(TOOLSLIB) $(UNOTOOLSLIB) $(I18NISOLANGLIB)
+ 
+ # Specifies an import library to create. For Win32 only.
+ SHL3IMPLIB=i$(TARGET3).lib
+Index: canvas/source/directx/dx_textlayout_drawhelper.cxx
+===================================================================
+--- canvas/source/directx/dx_textlayout_drawhelper.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ canvas/source/directx/dx_textlayout_drawhelper.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -52,6 +52,7 @@
+ #include <canvas/debug.hxx>
+ #include "dx_impltools.hxx"
+ #include <vcl/sysdata.hxx>
++#include <i18npool/mslangid.hxx>
+ #include "dx_textlayout_drawhelper.hxx"
+ #include "dx_bitmap.hxx"
+ #include "dx_canvasfont.hxx"
+@@ -135,6 +136,8 @@
+             aFont.SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
+             aFont.SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
+ 
++            aFont.SetLanguage(MsLangId::convertLocaleToLanguage(rFontRequest.Locale));
++
+             // setup font color
+             aFont.SetColor( aColor );
+             aFont.SetFillColor( aColor );
+Index: canvas/source/vcl/makefile.mk
+===================================================================
+--- canvas/source/vcl/makefile.mk	(.../tags/DEV300_m49)	(Revision 273505)
++++ canvas/source/vcl/makefile.mk	(.../cws/graphite01)	(Revision 273505)
+@@ -73,7 +73,7 @@
+ 
+ SHL1TARGET=$(TARGET).uno
+ 
+-SHL1STDLIBS= $(TOOLSLIB) $(TKLIB) $(CPPULIB) $(SALLIB) $(VCLLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(GOODIESLIB)
++SHL1STDLIBS= $(TOOLSLIB) $(TKLIB) $(CPPULIB) $(SALLIB) $(VCLLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(GOODIESLIB) $(I18NISOLANGLIB)
+ 
+ SHL1IMPLIB=i$(TARGET)
+ SHL1LIBS=$(SLB)$/$(TARGET).lib
+Index: canvas/source/vcl/canvasfont.cxx
+===================================================================
+--- canvas/source/vcl/canvasfont.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ canvas/source/vcl/canvasfont.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -35,7 +35,7 @@
+ 
+ #include <rtl/math.hxx>
+ #include <basegfx/numeric/ftools.hxx>
+-
++#include <i18npool/mslangid.hxx>
+ #include <vcl/metric.hxx>
+ 
+ #include "canvasfont.hxx"
+@@ -67,6 +67,8 @@
+         maFont->SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
+         maFont->SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
+ 
++		maFont->SetLanguage(MsLangId::convertLocaleToLanguage(rFontRequest.Locale));
++
+         // adjust to stretched/shrinked font
+         if( !::rtl::math::approxEqual( rFontMatrix.m00, rFontMatrix.m11) )
+         {
+Index: canvas/source/cairo/cairo_canvasfont.cxx
+===================================================================
+--- canvas/source/cairo/cairo_canvasfont.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ canvas/source/cairo/cairo_canvasfont.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -37,6 +37,7 @@
+ #include <basegfx/numeric/ftools.hxx>
+ 
+ #include <vcl/metric.hxx>
++#include <i18npool/mslangid.hxx>
+ 
+ #include "cairo_canvasfont.hxx"
+ #include "cairo_textlayout.hxx"
+@@ -86,6 +87,8 @@
+         maFont->SetWeight( static_cast<FontWeight>(rFontRequest.FontDescription.FontDescription.Weight) );
+         maFont->SetItalic( (rFontRequest.FontDescription.FontDescription.Letterform<=8) ? ITALIC_NONE : ITALIC_NORMAL );
+ 
++        maFont->SetLanguage(MsLangId::convertLocaleToLanguage(rFontRequest.Locale));
++
+         // adjust to stretched/shrinked font
+         if( !::rtl::math::approxEqual( rFontMatrix.m00, rFontMatrix.m11) )
+         {
+Index: canvas/source/cairo/makefile.mk
+===================================================================
+--- canvas/source/cairo/makefile.mk	(.../tags/DEV300_m49)	(Revision 273505)
++++ canvas/source/cairo/makefile.mk	(.../cws/graphite01)	(Revision 273505)
+@@ -84,7 +84,7 @@
+ 
+ SHL1TARGET=$(TARGET).uno
+ 
+-SHL1STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(VCLLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(TOOLSLIB)
++SHL1STDLIBS= $(CPPULIB) $(TKLIB) $(SALLIB) $(VCLLIB) $(COMPHELPERLIB) $(CPPUHELPERLIB) $(BASEGFXLIB) $(CANVASTOOLSLIB) $(TOOLSLIB) $(I18NISOLANGLIB)
+ 
+ .IF "$(GUI)"=="UNX" 
+ 
+Index: svx/source/editeng/impedit2.cxx
+===================================================================
+--- svx/source/editeng/impedit2.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ svx/source/editeng/impedit2.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -1743,7 +1743,7 @@
+ 		::rtl::OUString aOUText( aText );
+ 		USHORT nTextLen = (USHORT)aOUText.getLength();
+ 
+-		long nPos = 0;
++		sal_Int32 nPos = 0;
+ 		short nScriptType = _xBI->getScriptType( aOUText, nPos );
+ 		rTypes.Insert( ScriptTypePosInfo( nScriptType, (USHORT)nPos, nTextLen ), rTypes.Count() );
+ 		nPos = _xBI->endOfScript( aOUText, nPos, nScriptType );
+@@ -1761,6 +1761,17 @@
+             }
+             else
+             {
++                if ( _xBI->getScriptType( aOUText, nPos - 1 ) == i18n::ScriptType::WEAK )
++                {
++                    switch ( u_charType(aOUText.iterateCodePoints(&nPos, 0) ) ) {
++                    case U_NON_SPACING_MARK:
++                    case U_ENCLOSING_MARK:
++                    case U_COMBINING_SPACING_MARK:
++                        --nPos;
++                        rTypes[rTypes.Count()-1].nEndPos--;
++                        break;
++                    }
++                }
+ 			    rTypes.Insert( ScriptTypePosInfo( nScriptType, (USHORT)nPos, nTextLen ), rTypes.Count() );
+             }
+ 
+Index: svx/source/dialog/fntctrl.cxx
+===================================================================
+--- svx/source/dialog/fntctrl.cxx	(.../tags/DEV300_m49)	(Revision 273505)
++++ svx/source/dialog/fntctrl.cxx	(.../cws/graphite01)	(Revision 273505)
+@@ -36,6 +36,7 @@
+ #include <sfx2/printer.hxx>		// SfxPrinter
+ #include <vcl/metric.hxx>
+ #include <vcl/svapp.hxx>
++#include <unicode/uchar.h>
+ #include <com/sun/star/uno/Reference.h>
+ #include <com/sun/star/i18n/XBreakIterator.hpp>
+ #include <com/sun/star/lang/XMultiServiceFactory.hpp>
+@@ -244,7 +245,25 @@
+         do
+         {
+             nChg = (xub_StrLen)xBreak->endOfScript( aText, nChg, nScript );
+-            aScriptChg.Insert( nChg, nCnt );
++            if (nChg < aText.Len() && nChg > 0 &&
++                (com::sun::star::i18n::ScriptType::WEAK ==
++                 xBreak->getScriptType(aText, nChg - 1)))
++            {
++                int8_t nType = u_charType(aText.GetChar(nChg) );
++                if (nType == U_NON_SPACING_MARK || nType == U_ENCLOSING_MARK ||
++                    nType == U_COMBINING_SPACING_MARK )
++                {
++                    aScriptChg.Insert( nChg - 1, nCnt );
++                }
++                else
++                {
++                    aScriptChg.Insert( nChg, nCnt );
++                }
++            }
++            else
++            {
++                aScriptChg.Insert( nChg, nCnt );
++            }
+             aScriptType.Insert( nScript, nCnt );
+             aTextWidth.Insert( ULONG(0), nCnt++ );
+ 


More information about the ooo-build-commit mailing list