[Libreoffice-commits] core.git: Branch 'libreoffice-5-0' - 19 commits - include/comphelper vcl/inc vcl/README.vars vcl/source vcl/win

Tor Lillqvist tml at collabora.com
Fri Aug 28 04:21:31 PDT 2015


 include/comphelper/windowserrorstring.hxx |   46 +
 vcl/README.vars                           |   23 
 vcl/inc/sft.hxx                           |   21 
 vcl/inc/win/salgdi.h                      |   14 
 vcl/source/fontsubset/sft.cxx             |   23 
 vcl/source/gdi/pdfwriter_impl.cxx         |   58 -
 vcl/win/source/gdi/salgdi.cxx             |    5 
 vcl/win/source/gdi/salgdi3.cxx            |   51 -
 vcl/win/source/gdi/winlayout.cxx          | 1346 +++++++++++-------------------
 vcl/win/source/gdi/winlayout.hxx          |   88 -
 10 files changed, 630 insertions(+), 1045 deletions(-)

New commits:
commit c7b4b5e6f5d7f6213ca06a1497816537f369d9c8
Author: Tor Lillqvist <tml at collabora.com>
Date:   Mon Aug 24 18:08:08 2015 +0300

    Don't attempt to cache glyphs that are vertical but the text direction isn't
    
    That is a too complex and rare case to bother with, I think.
    
    Change-Id: Ica6ef7fa05314d2367dcff32627c1aec6ba8f8df
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 85b1e97..f26d3eb 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -353,6 +353,9 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
         aChunk.mbVertical = false;
     }
 
+    if (aChunk.mbVertical && aLogfont.lfEscapement != 2700)
+        return false;
+
     OpenGLCompatibleDC aDC(rGraphics, 0, 0, nBitmapWidth, nBitmapHeight);
 
     HFONT hNonAntialiasedFont = NULL;
commit 0f3c6f89b9819495a6268cf859e741e0e6d04f2c
Author: Tor Lillqvist <tml at collabora.com>
Date:   Fri Aug 21 16:19:31 2015 +0300

    Error handling
    
    Change-Id: I46e5463aaa5cab41cd69c13314ee98a0c73e7ba2
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 150bfa2..85b1e97 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -271,6 +271,8 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
     if (!GetCharABCWidthsI(hDC, 0, nCount, aGlyphIndices.data(), aABC.data()))
     {
         SAL_WARN("vcl.gdi", "GetCharABCWidthsI failed: " << WindowsErrorString(GetLastError()));
+        SelectObject(hDC, hOrigFont);
+        DeleteDC(hDC);
         return false;
     }
 
@@ -296,14 +298,34 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
     }
 
     TEXTMETRICW aTextMetric;
-    GetTextMetricsW(hDC, &aTextMetric);
+    if (!GetTextMetricsW(hDC, &aTextMetric))
+    {
+        SAL_WARN("vcl.gdi", "GetTextMetrics failed: " << WindowsErrorString(GetLastError()));
+        SelectObject(hDC, hOrigFont);
+        DeleteDC(hDC);
+        return false;
+    }
     aChunk.mnAscentPlusIntLeading = aTextMetric.tmAscent + aTextMetric.tmInternalLeading;
 
     LOGFONTW aLogfont;
-    GetObjectW(rLayout.mhFont, sizeof(aLogfont), &aLogfont);
+    if (!GetObjectW(rLayout.mhFont, sizeof(aLogfont), &aLogfont))
+    {
+        SAL_WARN("vcl.gdi", "GetObject failed: " << WindowsErrorString(GetLastError()));
+        SelectObject(hDC, hOrigFont);
+        DeleteDC(hDC);
+        return false;
+    }
 
     wchar_t sFaceName[200];
     int nFaceNameLen = GetTextFaceW(hDC, SAL_N_ELEMENTS(sFaceName), sFaceName);
+    if (!nFaceNameLen)
+    {
+        SAL_WARN("vcl.gdi", "GetTextFace failed: " << WindowsErrorString(GetLastError()));
+        SelectObject(hDC, hOrigFont);
+        DeleteDC(hDC);
+        return false;
+    }
+
     SAL_INFO("vcl.gdi.opengl", OUString(sFaceName, nFaceNameLen) <<
              ": Escapement=" << aLogfont.lfEscapement <<
              " Orientation=" << aLogfont.lfOrientation <<
commit eaf20241305b7f75e29a28d21ea2428e438f68ce
Author: Tor Lillqvist <tml at collabora.com>
Date:   Fri Aug 21 16:04:07 2015 +0300

    Make vertical fonts show up when using OpenGL glyph caching
    
    Change-Id: I6b19873eef48b625dc3d4f7b3a9afdb348189b38
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index d445506..150bfa2 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -65,6 +65,7 @@ struct OpenGLGlyphCacheChunk
     std::vector<Rectangle> maLocation;
     std::shared_ptr<OpenGLTexture> mpTexture;
     int mnAscentPlusIntLeading;
+    bool mbVertical;
 };
 
 // win32 specific physical font instance
@@ -130,13 +131,18 @@ OUString DumpGlyphBitmap(OpenGLGlyphCacheChunk& rChunk, HDC hDC)
     }
 
     std::cerr << "Bitmap " << hBitmap << ": " << aBitmap.bmWidth << "x" << aBitmap.bmHeight << ":" << std::endl;
+
+    // Print out start pos of each glyph only in the horizontal font case
     int nPos = 0;
-    for (int i = 1; i < rChunk.mnGlyphCount && nPos < 75; i++)
+    if (rChunk.mnGlyphCount > 1 && rChunk.maLocation[1].Left() > rChunk.maLocation[0].Left())
     {
-        for (int j = nPos; j < rChunk.maLocation[i].Left(); j++)
-            std::cerr << " ";
-        std::cerr << "!";
-        nPos = rChunk.maLocation[i].Left() + 1;
+        for (int i = 1; i < rChunk.mnGlyphCount && nPos < 75; i++)
+        {
+            for (int j = nPos; j < rChunk.maLocation[i].Left(); j++)
+                std::cerr << " ";
+            std::cerr << "!";
+            nPos = rChunk.maLocation[i].Left() + 1;
+        }
     }
     std::cerr << std::endl;
 
@@ -289,7 +295,21 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
         totWidth += aDX[i];
     }
 
-    SAL_INFO("vcl.gdi.opengl", "aSize=(" << aSize.cx << "," << aSize.cy << ") totWidth=" << totWidth);
+    TEXTMETRICW aTextMetric;
+    GetTextMetricsW(hDC, &aTextMetric);
+    aChunk.mnAscentPlusIntLeading = aTextMetric.tmAscent + aTextMetric.tmInternalLeading;
+
+    LOGFONTW aLogfont;
+    GetObjectW(rLayout.mhFont, sizeof(aLogfont), &aLogfont);
+
+    wchar_t sFaceName[200];
+    int nFaceNameLen = GetTextFaceW(hDC, SAL_N_ELEMENTS(sFaceName), sFaceName);
+    SAL_INFO("vcl.gdi.opengl", OUString(sFaceName, nFaceNameLen) <<
+             ": Escapement=" << aLogfont.lfEscapement <<
+             " Orientation=" << aLogfont.lfOrientation <<
+             " Ascent=" << aTextMetric.tmAscent <<
+             " InternalLeading=" << aTextMetric.tmInternalLeading <<
+             " Size=(" << aSize.cx << "," << aSize.cy << ") totWidth=" << totWidth);
 
     if (SelectObject(hDC, hOrigFont) == NULL)
         SAL_WARN("vcl.gdi", "SelectObject failed: " << WindowsErrorString(GetLastError()));
@@ -297,7 +317,21 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
         SAL_WARN("vcl.gdi", "DeleteDC failed: " << WindowsErrorString(GetLastError()));
 
     // Leave two pixels of extra space also at top and bottom
-    OpenGLCompatibleDC aDC(rGraphics, 0, 0, totWidth, aSize.cy + 4);
+    int nBitmapWidth, nBitmapHeight;
+    if (sFaceName[0] == '@')
+    {
+        nBitmapWidth = aSize.cy + 4;
+        nBitmapHeight = totWidth;
+        aChunk.mbVertical = true;
+    }
+    else
+    {
+        nBitmapWidth = totWidth;
+        nBitmapHeight = aSize.cy + 4;
+        aChunk.mbVertical = false;
+    }
+
+    OpenGLCompatibleDC aDC(rGraphics, 0, 0, nBitmapWidth, nBitmapHeight);
 
     HFONT hNonAntialiasedFont = NULL;
 
@@ -305,12 +339,6 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
     static bool bNoAntialias = (std::getenv("VCL_GLYPH_CACHING_HACK_NO_ANTIALIAS") != NULL);
     if (bNoAntialias)
     {
-        LOGFONTW aLogfont;
-        if (!GetObjectW(rLayout.mhFont, sizeof(aLogfont), &aLogfont))
-        {
-            SAL_WARN("vcl.gdi", "GetObject failed: " << WindowsErrorString(GetLastError()));
-            return false;
-        }
         aLogfont.lfQuality = NONANTIALIASED_QUALITY;
         hNonAntialiasedFont = CreateFontIndirectW(&aLogfont);
         if (hNonAntialiasedFont == NULL)
@@ -334,7 +362,11 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
     aDC.fill(MAKE_SALCOLOR(0xff, 0xff, 0xff));
 
     // The 2,2 is for the extra space
-    if (!ExtTextOutW(aDC.getCompatibleHDC(), 2, 2, ETO_GLYPH_INDEX, NULL, aGlyphIndices.data(), nCount, aDX.data()))
+    int nY = 2;
+    int nX = 2;
+    if (aChunk.mbVertical)
+        nX += aDX[0];
+    if (!ExtTextOutW(aDC.getCompatibleHDC(), nX, nY, ETO_GLYPH_INDEX, NULL, aGlyphIndices.data(), nCount, aDX.data()))
     {
         SAL_WARN("vcl.gdi", "ExtTextOutW failed: " << WindowsErrorString(GetLastError()));
         SelectFont(aDC.getCompatibleHDC(), hOrigFont);
@@ -347,19 +379,26 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
     UINT nPos = 0;
     for (int i = 0; i < nCount; i++)
     {
-        aChunk.maLocation[i].Left() = nPos;
-        aChunk.maLocation[i].Right() = nPos + aDX[i];
-        nPos = aChunk.maLocation[i].Right();
-        aChunk.maLocation[i].Top() = 0;
-        aChunk.maLocation[i].Bottom() = aSize.cy + 4;
+        if (aChunk.mbVertical)
+        {
+            aChunk.maLocation[i].Left() = 0;
+            aChunk.maLocation[i].Right() = nBitmapWidth;
+            aChunk.maLocation[i].Top() = nPos;
+            aChunk.maLocation[i].Bottom() = nPos + aDX[i];
+            nPos = aChunk.maLocation[i].Bottom();
+        }
+        else
+        {
+            aChunk.maLocation[i].Left() = nPos;
+            aChunk.maLocation[i].Right() = nPos + aDX[i];
+            nPos = aChunk.maLocation[i].Right();
+            aChunk.maLocation[i].Top() = 0;
+            aChunk.maLocation[i].Bottom() = aSize.cy + 4;
+        }
     }
 
     aChunk.mpTexture = std::unique_ptr<OpenGLTexture>(aDC.getTexture());
 
-    TEXTMETRICW aTextMetric;
-    GetTextMetricsW(aDC.getCompatibleHDC(), &aTextMetric);
-    aChunk.mnAscentPlusIntLeading = aTextMetric.tmAscent + aTextMetric.tmInternalLeading;
-
     maOpenGLGlyphCache.insert(n, aChunk);
 
     SelectFont(aDC.getCompatibleHDC(), hOrigFont);
@@ -1670,11 +1709,22 @@ bool UniscribeLayout::DrawCachedGlyphs(SalGraphics& rGraphics) const
             const OpenGLGlyphCacheChunk& rChunk = mrWinFontEntry.GetCachedGlyphChunkFor(mpOutGlyphs[i]);
             const int n = mpOutGlyphs[i] - rChunk.mnFirstGlyph;
 
-            SalTwoRect a2Rects(rChunk.maLocation[n].Left(), rChunk.maLocation[n].Top(),
-                               rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight(),
-                               nAdvance + aPos.X() + mpGlyphOffsets[i].du, aPos.Y() + mpGlyphOffsets[i].dv - rChunk.mnAscentPlusIntLeading,
-                               rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight()); // ???
-            pImpl->DrawMask(*rChunk.mpTexture, salColor, a2Rects);
+            if (rChunk.mbVertical)
+            {
+                SalTwoRect a2Rects(rChunk.maLocation[n].Left(), rChunk.maLocation[n].Top(),
+                                   rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight(),
+                                   aPos.X(), nAdvance + aPos.Y(),
+                                   rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight()); // ???
+                pImpl->DrawMask(*rChunk.mpTexture, salColor, a2Rects);
+            }
+            else
+            {
+                SalTwoRect a2Rects(rChunk.maLocation[n].Left(), rChunk.maLocation[n].Top(),
+                                   rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight(),
+                                   nAdvance + aPos.X() + mpGlyphOffsets[i].du, aPos.Y() + mpGlyphOffsets[i].dv - rChunk.mnAscentPlusIntLeading,
+                                   rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight()); // ???
+                pImpl->DrawMask(*rChunk.mpTexture, salColor, a2Rects);
+            }
             nAdvance += mpGlyphAdvances[i];
         }
     }
commit 3665c4b13384abd009b87ef21e05ce4a00d55f8f
Author: Tor Lillqvist <tml at collabora.com>
Date:   Fri Aug 21 12:58:00 2015 +0300

    No NO_MAPPERS, NO_TYPE3, NO_TYPE42 or NO_TTCR anywhere
    
    Change-Id: Icab5608900108c89e649e78a2e35d02e941d0ac0
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/inc/sft.hxx b/vcl/inc/sft.hxx
index 2aae5f7..3c08689 100644
--- a/vcl/inc/sft.hxx
+++ b/vcl/inc/sft.hxx
@@ -24,16 +24,6 @@
  */
 
 /*
- *        If NO_MAPPERS is defined, MapChar() and MapString() and consequently GetTTSimpleCharMetrics()
- *        don't get compiled in. This is done to avoid including a large chunk of code (TranslateXY() from
- *        xlat.c in the projects that don't require it.
- *
- *        If NO_TYPE3 is defined CreateT3FromTTGlyphs() does not get compiled in.
- *        If NO_TYPE42 is defined Type42-related code is excluded
- *        If NO_TTCR is defined TrueType creation related code is excluded\
- */
-
-/*
  *        Generated fonts contain an XUID entry in the form of:
  *
  *                  103 0 T C1 N C2 C3
@@ -140,7 +130,6 @@ namespace vcl
         OVERLAP_COMPOUND          = 1<<10
     };
 
-#ifndef NO_TTCR
 /** Flags for TrueType generation */
     enum TTCreationFlags {
         TTCF_AutoName = 1,                  /**< Automatically generate a compact 'name' table.
@@ -156,7 +145,6 @@ namespace vcl
         TTCF_IncludeOS2 = 2                 /** If this flag is set OS/2 table from the original font will be
                                                 copied to the subset */
     };
-#endif
 
 /** Structure used by GetTTSimpleGlyphMetrics() and GetTTSimpleCharMetrics() functions */
     typedef struct {
@@ -364,7 +352,6 @@ namespace vcl
  */
     void DisposeNameRecords(NameRecord* nr, int n);
 
-#ifndef NO_TYPE3
 /**
  * Generates a new PostScript Type 3 font and dumps it to <b>outf</b> file.
  * This function substitutes glyph 0 for all glyphIDs that are not found in the font.
@@ -383,9 +370,7 @@ namespace vcl
  *
  */
     int  CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname, sal_uInt16 *glyphArray, sal_uInt8 *encoding, int nGlyphs, int wmode);
-#endif
 
-#ifndef NO_TTCR
 /**
  * Generates a new TrueType font and dumps it to <b>outf</b> file.
  * This function substitutes glyph 0 for all glyphIDs that are not found in the font.
@@ -414,9 +399,7 @@ namespace vcl
                               int            nNameRecs,
                               NameRecord    *nr,
                               sal_uInt32        flags);
-#endif
 
-#ifndef NO_TYPE42
 /**
  * Generates a new PostScript Type42 font and dumps it to <b>outf</b> file.
  * This function substitutes glyph 0 for all glyphIDs that are not found in the font.
@@ -443,7 +426,6 @@ namespace vcl
                                sal_uInt16        *glyphArray,
                                sal_uInt8          *encoding,
                                int            nGlyphs);
-#endif
 
 /**
  * Queries glyph metrics. Allocates an array of TTSimpleGlyphMetrics structs and returns it.
@@ -457,7 +439,6 @@ namespace vcl
  */
     TTSimpleGlyphMetrics *GetTTSimpleGlyphMetrics(TrueTypeFont *ttf, sal_uInt16 *glyphArray, int nGlyphs, bool vertical);
 
-#ifndef NO_MAPPERS
 /**
  * Queries glyph metrics. Allocates an array of TTSimpleGlyphMetrics structs and returns it.
  * This function behaves just like GetTTSimpleGlyphMetrics() but it takes a range of Unicode
@@ -512,8 +493,6 @@ namespace vcl
  */
     int DoesVerticalSubstitution( TrueTypeFont *ttf, int bvertical);
 
-#endif
-
 /**
  * Returns global font information about the TrueType font.
  * @see TTGlobalFontInfo
diff --git a/vcl/source/fontsubset/sft.cxx b/vcl/source/fontsubset/sft.cxx
index dfd5d20..6758df2 100644
--- a/vcl/source/fontsubset/sft.cxx
+++ b/vcl/source/fontsubset/sft.cxx
@@ -35,15 +35,9 @@
 #endif
 #include "sft.hxx"
 #include "gsub.h"
-#if ! (defined(NO_TTCR) && defined(NO_TYPE42))
 #include "ttcr.hxx"
-#endif
-#ifndef NO_MAPPERS            /* include MapChar() and MapString() */
 #include "xlat.hxx"
-#endif
-#ifndef NO_TYPE3              /* include CreateT3FromTTGlyphs() */
 #include <rtl/crc.h>
-#endif
 #include <rtl/ustring.hxx>
 
 #include <osl/endian.h>
@@ -308,7 +302,6 @@ _inline sal_uInt32 getTableSize(TrueTypeFont *ttf, sal_uInt32 ord)
     return ttf->tlens[ord];
 }
 
-#ifndef NO_TYPE42
 /* Hex Formatter functions */
 static const char HexChars[] = "0123456789ABCDEF";
 
@@ -371,7 +364,6 @@ static void HexFmtBlockWrite(HexFmt *_this, const void *ptr, sal_uInt32 size)
     }
     _this->total += size;
 }
-#endif
 
 /* Outline Extraction functions */
 
@@ -724,8 +716,6 @@ static int GetTTGlyphOutline(TrueTypeFont *ttf, sal_uInt32 glyphID, ControlPoint
     return res;
 }
 
-#ifndef NO_TYPE3
-
 /*- returns the number of items in the path -*/
 
 static int BSplineToPSPath(ControlPoint *srcA, int srcCount, PSPathElement **path)
@@ -854,8 +844,6 @@ static int BSplineToPSPath(ControlPoint *srcA, int srcCount, PSPathElement **pat
     return nPathCount;
 }
 
-#endif
-
 /*- Extracts a string from the name table and allocates memory for it -*/
 
 static char *nameExtract( const sal_uInt8* name, int nTableSize, int n, int dbFlag, sal_uInt16** ucs2result )
@@ -1814,7 +1802,6 @@ int GetTTGlyphComponents(TrueTypeFont *ttf, sal_uInt32 glyphID, std::vector< sal
     return n;
 }
 
-#ifndef NO_TYPE3
 int  CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname,
                           sal_uInt16 *glyphArray, sal_uInt8 *encoding, int nGlyphs,
                           int wmode)
@@ -1966,9 +1953,7 @@ int  CreateT3FromTTGlyphs(TrueTypeFont *ttf, FILE *outf, const char *fname,
 
     return SF_OK;
 }
-#endif
 
-#ifndef NO_TTCR
 int  CreateTTFromTTGlyphs(TrueTypeFont  *ttf,
                           const char    *fname,
                           sal_uInt16        *glyphArray,
@@ -2112,9 +2097,7 @@ int  CreateTTFromTTGlyphs(TrueTypeFont  *ttf,
 
     return res;
 }
-#endif
 
-#ifndef NO_TYPE42
 static GlyphOffsets *GlyphOffsetsNew(sal_uInt8 *sfntP, sal_uInt32 sfntLen)
 {
     GlyphOffsets* res = static_cast<GlyphOffsets*>(smalloc(sizeof(GlyphOffsets)));
@@ -2372,9 +2355,7 @@ int  CreateT42FromTTGlyphs(TrueTypeFont  *ttf,
     free(sfntP);
     return SF_OK;
 }
-#endif
 
-#ifndef NO_MAPPERS
 int MapString(TrueTypeFont *ttf, sal_uInt16 *str, int nchars, sal_uInt16 *glyphArray, bool bvertical)
 {
     int i;
@@ -2460,8 +2441,6 @@ int DoesVerticalSubstitution( TrueTypeFont *ttf, int bvertical)
     return nRet;
 }
 
-#endif
-
 int GetTTGlyphCount( TrueTypeFont* ttf )
 {
     return ttf->nglyphs;
@@ -2532,7 +2511,6 @@ TTSimpleGlyphMetrics *GetTTSimpleGlyphMetrics(TrueTypeFont *ttf, sal_uInt16 *gly
     return res;
 }
 
-#ifndef NO_MAPPERS
 TTSimpleGlyphMetrics *GetTTSimpleCharMetrics(TrueTypeFont * ttf, sal_uInt16 firstChar, int nChars, bool vertical)
 {
     TTSimpleGlyphMetrics *res = 0;
@@ -2550,7 +2528,6 @@ TTSimpleGlyphMetrics *GetTTSimpleCharMetrics(TrueTypeFont * ttf, sal_uInt16 firs
 
     return res;
 }
-#endif
 
 void GetTTGlobalFontInfo(TrueTypeFont *ttf, TTGlobalFontInfo *info)
 {
commit 4b062fabe992ac9ef1037acb2598973809f161cd
Author: Tor Lillqvist <tml at collabora.com>
Date:   Thu Aug 20 15:40:40 2015 +0300

    Adjust for the TA_BASELINE of the DC
    
    The text alignment of DCs is set to TA_BASELINE in
    WinSalGraphics::InitGraphics(). In the ScriptTextOut-using old code
    path this affects where glyphs are put, so we need to take it into
    consideration also in the new code path that uses cached glyph
    textures. Adjusting the position up by the ascent plus internal
    leading of the font seems to work at least for horizontal scripts.
    
    (We used to bluntly adjust the position up by the height of the glyph
    cache texture, which was too much. The glyphs got positioned too high
    and the top of tall ones was clipped.)
    
    Change-Id: I86aecd6f3016e14b2f0328555ddfd3129e394c4c
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 315d983..d445506 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -64,6 +64,7 @@ struct OpenGLGlyphCacheChunk
     int mnGlyphCount;
     std::vector<Rectangle> maLocation;
     std::shared_ptr<OpenGLTexture> mpTexture;
+    int mnAscentPlusIntLeading;
 };
 
 // win32 specific physical font instance
@@ -355,6 +356,10 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
 
     aChunk.mpTexture = std::unique_ptr<OpenGLTexture>(aDC.getTexture());
 
+    TEXTMETRICW aTextMetric;
+    GetTextMetricsW(aDC.getCompatibleHDC(), &aTextMetric);
+    aChunk.mnAscentPlusIntLeading = aTextMetric.tmAscent + aTextMetric.tmInternalLeading;
+
     maOpenGLGlyphCache.insert(n, aChunk);
 
     SelectFont(aDC.getCompatibleHDC(), hOrigFont);
@@ -1667,7 +1672,7 @@ bool UniscribeLayout::DrawCachedGlyphs(SalGraphics& rGraphics) const
 
             SalTwoRect a2Rects(rChunk.maLocation[n].Left(), rChunk.maLocation[n].Top(),
                                rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight(),
-                               nAdvance + aPos.X() + mpGlyphOffsets[i].du, aPos.Y() + mpGlyphOffsets[i].dv - rChunk.maLocation[n].getHeight(),
+                               nAdvance + aPos.X() + mpGlyphOffsets[i].du, aPos.Y() + mpGlyphOffsets[i].dv - rChunk.mnAscentPlusIntLeading,
                                rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight()); // ???
             pImpl->DrawMask(*rChunk.mpTexture, salColor, a2Rects);
             nAdvance += mpGlyphAdvances[i];
commit 8e3cf27c919f8eecd8ae2a5e70cee102a5564566
Author: Tor Lillqvist <tml at collabora.com>
Date:   Thu Aug 20 13:37:13 2015 +0300

    Drop code that is dead after 4667db065d34193d99bce82f7e8f3b20a03ecade
    
    Change-Id: Id023b43e901b0e41ebf3b208c6e80fd023bf7f9a
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index a700fac..f499a31 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -214,9 +214,6 @@ private:
     RGNDATA*                mpClipRgnData;      // ClipRegion-Data
     RGNDATA*                mpStdClipRgnData;   // Cache Standard-ClipRegion-Data
     ImplFontAttrCache*      mpFontAttrCache;    // Cache font attributes from files in so/share/fonts
-    bool                    mbFontKernInit;     // FALSE: FontKerns must be queried
-    KERNINGPAIR*            mpFontKernPairs;    // Kerning Pairs of the current Font
-    sal_uIntPtr             mnFontKernPairCount;// Number of Kerning Pairs of the current Font
     int                     mnPenWidth;         // Linienbreite
 
 public:
@@ -336,12 +333,6 @@ protected:
                            const SalBitmap* pAlphaBitmap) SAL_OVERRIDE;
     virtual bool       drawAlphaRect( long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency ) SAL_OVERRIDE;
 
-private:
-    // local helpers
-
-    // get kernign pairs of the current font
-    sal_uLong               GetKernPairs();
-
 public:
     // public SalGraphics methods, the interface to the independent vcl part
 
@@ -470,7 +461,7 @@ void    ImplGetLogFontFromFontSelect( HDC, const FontSelectPattern*,
 #define MAX_64KSALPOINTS    ((((sal_uInt16)0xFFFF)-8)/sizeof(POINTS))
 
 // #102411# Win's GCP mishandles kerning => we need to do it ourselves
-// SalGraphicsData::mpFontKernPairs is sorted by
+// kerning pairs is sorted by
 inline bool ImplCmpKernData( const KERNINGPAIR& a, const KERNINGPAIR& b )
 {
     if( a.wFirst < b.wFirst )
diff --git a/vcl/win/source/gdi/salgdi.cxx b/vcl/win/source/gdi/salgdi.cxx
index 23d4e5c..64d4952 100644
--- a/vcl/win/source/gdi/salgdi.cxx
+++ b/vcl/win/source/gdi/salgdi.cxx
@@ -634,9 +634,6 @@ WinSalGraphics::WinSalGraphics(WinSalGraphics::Type eType, bool bScreen, HWND hW
     mhDefPal(0),
     mpStdClipRgnData(NULL),
     mpFontAttrCache(NULL),
-    mpFontKernPairs(NULL),
-    mnFontKernPairCount(0),
-    mbFontKernInit(false),
     mnPenWidth(GSL_PEN_WIDTH)
 {
     if (OpenGLHelper::isVCLOpenGLEnabled() && !mbPrinter)
@@ -666,8 +663,6 @@ WinSalGraphics::~WinSalGraphics()
 
     // delete cache data
     delete [] mpStdClipRgnData;
-
-    delete [] mpFontKernPairs;
 }
 
 SalGraphicsImpl* WinSalGraphics::GetImpl() const
diff --git a/vcl/win/source/gdi/salgdi3.cxx b/vcl/win/source/gdi/salgdi3.cxx
index c70d868..419fa26a 100644
--- a/vcl/win/source/gdi/salgdi3.cxx
+++ b/vcl/win/source/gdi/salgdi3.cxx
@@ -1559,17 +1559,6 @@ sal_uInt16 WinSalGraphics::SetFont( FontSelectPattern* pFont, int nFallbackLevel
     if( mpWinFontData[ nFallbackLevel ] )
         mpWinFontData[ nFallbackLevel ]->UpdateFromHDC( getHDC() );
 
-    if( !nFallbackLevel )
-    {
-        mbFontKernInit = TRUE;
-        if ( mpFontKernPairs )
-        {
-            delete[] mpFontKernPairs;
-            mpFontKernPairs = NULL;
-        }
-        mnFontKernPairCount = 0;
-    }
-
     // some printers have higher internal resolution, so their
     // text output would be different from what we calculated
     // => suggest DrawTextArray to workaround this problem
@@ -1655,35 +1644,6 @@ void WinSalGraphics::GetFontMetric( ImplFontMetricData* pMetric, int nFallbackLe
     pMetric->mnMinKashida = GetMinKashidaWidth();
 }
 
-sal_uLong WinSalGraphics::GetKernPairs()
-{
-    if ( mbFontKernInit )
-    {
-        if( mpFontKernPairs )
-        {
-            delete[] mpFontKernPairs;
-            mpFontKernPairs = NULL;
-        }
-        mnFontKernPairCount = 0;
-
-        KERNINGPAIR* pPairs = NULL;
-        int nCount = ::GetKerningPairsW( getHDC(), 0, NULL );
-        if( nCount )
-        {
-            pPairs = new KERNINGPAIR[ nCount+1 ];
-            mpFontKernPairs = pPairs;
-            mnFontKernPairCount = nCount;
-            ::GetKerningPairsW( getHDC(), nCount, pPairs );
-        }
-
-        mbFontKernInit = FALSE;
-
-        std::sort( mpFontKernPairs, mpFontKernPairs + mnFontKernPairCount, ImplCmpKernData );
-    }
-
-    return mnFontKernPairCount;
-}
-
 const FontCharMapPtr WinSalGraphics::GetFontCharMap() const
 {
     if( !mpWinFontData[0] )
diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index c1c2d7e..315d983 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -77,14 +77,6 @@ private:
     // TODO: also add HFONT??? Watch out for issues with too many active fonts...
 
 public:
-    bool                    HasKernData() const;
-    void                    SetKernData( int, const KERNINGPAIR* );
-    int                     GetKerning( sal_Unicode, sal_Unicode ) const;
-private:
-    KERNINGPAIR*            mpKerningPairs;
-    int                     mnKerningPairs;
-
-public:
     SCRIPT_CACHE&           GetScriptCache() const
                             { return maScriptCache; }
 private:
@@ -2426,8 +2418,6 @@ int    WinSalGraphics::GetMinKashidaWidth()
 
 ImplWinFontEntry::ImplWinFontEntry( FontSelectPattern& rFSD )
 :   ImplFontEntry( rFSD )
-,   mpKerningPairs( NULL )
-,   mnKerningPairs( -1 )
 ,   maWidthMap( 512 )
 ,    mnMinKashidaWidth( -1 )
 ,    mnMinKashidaGlyph( -1 )
@@ -2439,38 +2429,6 @@ ImplWinFontEntry::~ImplWinFontEntry()
 {
     if( maScriptCache != NULL )
         ScriptFreeCache( &maScriptCache );
-    delete[] mpKerningPairs;
-}
-
-bool ImplWinFontEntry::HasKernData() const
-{
-    return (mnKerningPairs >= 0);
-}
-
-void ImplWinFontEntry::SetKernData( int nPairCount, const KERNINGPAIR* pPairData )
-{
-    mnKerningPairs = nPairCount;
-    mpKerningPairs = new KERNINGPAIR[ mnKerningPairs ];
-    memcpy( mpKerningPairs, (const void*)pPairData, nPairCount*sizeof(KERNINGPAIR) );
-}
-
-int ImplWinFontEntry::GetKerning( sal_Unicode cLeft, sal_Unicode cRight ) const
-{
-    int nKernAmount = 0;
-    if( mpKerningPairs )
-    {
-        const KERNINGPAIR aRefPair = { cLeft, cRight, 0 };
-        const KERNINGPAIR* pFirstPair = mpKerningPairs;
-        const KERNINGPAIR* pEndPair = mpKerningPairs + mnKerningPairs;
-        const KERNINGPAIR* pPair = std::lower_bound( pFirstPair,
-            pEndPair, aRefPair, ImplCmpKernData );
-        if( (pPair != pEndPair)
-        &&  (pPair->wFirst == aRefPair.wFirst)
-        &&  (pPair->wSecond == aRefPair.wSecond) )
-            nKernAmount = pPair->iKernAmount;
-    }
-
-    return nKernAmount;
 }
 
 bool ImplWinFontEntry::InitKashidaHandling( HDC hDC )
commit da5892c962cfc91fe3d688db6d3b994a223e2a6b
Author: Tor Lillqvist <tml at collabora.com>
Date:   Wed Aug 19 15:44:30 2015 +0300

    Still more hacking on OpenGL glyph caching for Windows
    
    Show the whole height of the cache bitmap after all (when SAL_LOG
    contains vcl.gdi.opengl). The interesting pieces are often at the
    bottom, like the tip of the hook of the "j" glyphs that used to bleed
    over into the preceding glyphs, usually "i", when they were rendered
    into the same chunk.
    
    Add more space between glyphs and at top and bottom of the bitmap, for
    anti-aliasing. The glyph ABC widths don't take expansions caused by
    anti-aliasing into consideration and are misleading. Hopefully
    anti-aliasing can expand the (partially) painted pixels of a glyph
    just one column/row in each direction, but for safety use a two-pixel
    border. (Defensive programming, eek?)
    
    Some getWidth() instead of GetWidth() etc craziness. Using
    <tools/gen.hxx> types truly is programming-by-coincidence as Thorsten
    says.
    
    In a dbgutil build, setting the environment variable
    VCL_GLYPH_CACHING_HACK_NO_ANTIALIAS causes the code to turn off
    anti-aliasing for the fonts used. I used this to verify that it indeed
    was anti-aliasing that made the ABC widths inconsistent with
    reality. Not sure if it makes sense to keep this code in?
    
    Anyway, now I don't see any leaked pixels in "i" glyphs any more,
    touch wood.
    
    Change-Id: If527343ff1dcdb1fa208cd5e7fa4d08f812d0d7b
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 540a76b..c1c2d7e 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -147,7 +147,7 @@ OUString DumpGlyphBitmap(OpenGLGlyphCacheChunk& rChunk, HDC hDC)
     }
     std::cerr << std::endl;
 
-    for (long y = 0; y < std::min(20l, aBitmap.bmHeight); y++)
+    for (long y = 0; y < aBitmap.bmHeight; y++)
     {
         for (long x = 0; x < std::min(75l, aBitmap.bmWidth); x++)
             std::cerr << ColorFor(GetPixel(hDC, x, y));
@@ -279,7 +279,10 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
         std::cerr << aABC[i].abcA << ":" << aABC[i].abcB << ":" << aABC[i].abcC << " ";
     std::cerr << std::endl;
 
-    // Avoid kerning as we want to be able to use individual rectangles for each glyph
+    // Try hard to avoid overlap as we want to be able to use
+    // individual rectangles for each glyph. The ABC widths don't
+    // take anti-alising into consideration. Let's hope that leaving
+    // four pixels of "extra" space inbetween glyphs will help.
     std::vector<int> aDX(nCount);
     int totWidth = 0;
     for (int i = 0; i < nCount; i++)
@@ -289,6 +292,7 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
             aDX[0] += std::abs(aABC[0].abcA);
         if (i < nCount-1)
             aDX[i] += std::abs(aABC[i+1].abcA);
+        aDX[i] += 4;
         totWidth += aDX[i];
     }
 
@@ -299,9 +303,32 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
     if (!DeleteDC(hDC))
         SAL_WARN("vcl.gdi", "DeleteDC failed: " << WindowsErrorString(GetLastError()));
 
-    OpenGLCompatibleDC aDC(rGraphics, 0, 0, totWidth, aSize.cy);
+    // Leave two pixels of extra space also at top and bottom
+    OpenGLCompatibleDC aDC(rGraphics, 0, 0, totWidth, aSize.cy + 4);
 
-    hOrigFont = SelectFont(aDC.getCompatibleHDC(), rLayout.mhFont);
+    HFONT hNonAntialiasedFont = NULL;
+
+#ifdef DBG_UTIL
+    static bool bNoAntialias = (std::getenv("VCL_GLYPH_CACHING_HACK_NO_ANTIALIAS") != NULL);
+    if (bNoAntialias)
+    {
+        LOGFONTW aLogfont;
+        if (!GetObjectW(rLayout.mhFont, sizeof(aLogfont), &aLogfont))
+        {
+            SAL_WARN("vcl.gdi", "GetObject failed: " << WindowsErrorString(GetLastError()));
+            return false;
+        }
+        aLogfont.lfQuality = NONANTIALIASED_QUALITY;
+        hNonAntialiasedFont = CreateFontIndirectW(&aLogfont);
+        if (hNonAntialiasedFont == NULL)
+        {
+            SAL_WARN("vcl.gdi", "CreateFontIndirect failed: " << WindowsErrorString(GetLastError()));
+            return false;
+        }
+    }
+#endif
+
+    hOrigFont = SelectFont(aDC.getCompatibleHDC(), hNonAntialiasedFont != NULL ? hNonAntialiasedFont : rLayout.mhFont);
     if (hOrigFont == NULL)
     {
         SAL_WARN("vcl.gdi", "SelectObject failed: " << WindowsErrorString(GetLastError()));
@@ -311,9 +338,15 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
     SetTextColor(aDC.getCompatibleHDC(), RGB(0, 0, 0));
     SetBkColor(aDC.getCompatibleHDC(), RGB(255, 255, 255));
 
-    if (!ExtTextOutW(aDC.getCompatibleHDC(), 0, 0, ETO_GLYPH_INDEX, NULL, aGlyphIndices.data(), nCount, aDX.data()))
+    aDC.fill(MAKE_SALCOLOR(0xff, 0xff, 0xff));
+
+    // The 2,2 is for the extra space
+    if (!ExtTextOutW(aDC.getCompatibleHDC(), 2, 2, ETO_GLYPH_INDEX, NULL, aGlyphIndices.data(), nCount, aDX.data()))
     {
         SAL_WARN("vcl.gdi", "ExtTextOutW failed: " << WindowsErrorString(GetLastError()));
+        SelectFont(aDC.getCompatibleHDC(), hOrigFont);
+        if (hNonAntialiasedFont != NULL)
+            DeleteObject(hNonAntialiasedFont);
         return false;
     }
 
@@ -325,7 +358,7 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
         aChunk.maLocation[i].Right() = nPos + aDX[i];
         nPos = aChunk.maLocation[i].Right();
         aChunk.maLocation[i].Top() = 0;
-        aChunk.maLocation[i].Bottom() = aSize.cy;
+        aChunk.maLocation[i].Bottom() = aSize.cy + 4;
     }
 
     aChunk.mpTexture = std::unique_ptr<OpenGLTexture>(aDC.getTexture());
@@ -333,6 +366,8 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
     maOpenGLGlyphCache.insert(n, aChunk);
 
     SelectFont(aDC.getCompatibleHDC(), hOrigFont);
+    if (hNonAntialiasedFont != NULL)
+        DeleteObject(hNonAntialiasedFont);
 
     SAL_INFO("vcl.gdi.opengl", "this=" << this << " now: " << maOpenGLGlyphCache << DumpGlyphBitmap(aChunk, aDC.getCompatibleHDC()));
 
@@ -1562,7 +1597,7 @@ void UniscribeLayout::DrawTextImpl(HDC hDC) const
 
 bool UniscribeLayout::CacheGlyphs(SalGraphics& rGraphics) const
 {
-    const bool bDoGlyphCaching = (std::getenv("SAL_ENABLE_GLYPH_CACHING") != NULL);
+    static bool bDoGlyphCaching = (std::getenv("SAL_ENABLE_GLYPH_CACHING") != NULL);
 
     if (!bDoGlyphCaching)
         return false;
@@ -1639,9 +1674,9 @@ bool UniscribeLayout::DrawCachedGlyphs(SalGraphics& rGraphics) const
             const int n = mpOutGlyphs[i] - rChunk.mnFirstGlyph;
 
             SalTwoRect a2Rects(rChunk.maLocation[n].Left(), rChunk.maLocation[n].Top(),
-                               rChunk.maLocation[n].GetWidth(), rChunk.maLocation[n].GetHeight(),
-                               nAdvance + aPos.X() + mpGlyphOffsets[i].du, aPos.Y() + mpGlyphOffsets[i].dv - rChunk.maLocation[n].GetHeight(),
-                               rChunk.maLocation[n].GetWidth(), rChunk.maLocation[n].GetHeight()); // ???
+                               rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight(),
+                               nAdvance + aPos.X() + mpGlyphOffsets[i].du, aPos.Y() + mpGlyphOffsets[i].dv - rChunk.maLocation[n].getHeight(),
+                               rChunk.maLocation[n].getWidth(), rChunk.maLocation[n].getHeight()); // ???
             pImpl->DrawMask(*rChunk.mpTexture, salColor, a2Rects);
             nAdvance += mpGlyphAdvances[i];
         }
commit b35f554787cc60e5f35d072ade69fd93911c7099
Author: Tor Lillqvist <tml at collabora.com>
Date:   Wed Aug 19 12:37:56 2015 +0300

    Make the pixel greylevel debug output work as intended
    
    Change-Id: I29cb771eb059f560b7cbd449257ffda581b40f11
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 7f4c4a4..540a76b 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -114,7 +114,10 @@ char ColorFor(COLORREF aColor)
 {
     if (aColor == RGB(0xFF, 0xFF, 0xFF))
         return ' ';
-    return '0' + 10*((GetRValue(aColor) + GetGValue(aColor) + GetBValue(aColor)) / (0xFF*3));
+    else if (aColor == RGB(0x00, 0x00, 0x00))
+        return 'X';
+
+    return '0' + (10*(GetRValue(aColor) + GetGValue(aColor) + GetBValue(aColor))) / (0xFF*3);
 }
 
 OUString DumpGlyphBitmap(OpenGLGlyphCacheChunk& rChunk, HDC hDC)
commit c037a53158b5fabb0103b6c25ed5a5da9144953b
Author: Tor Lillqvist <tml at collabora.com>
Date:   Wed Aug 19 09:30:26 2015 +0300

    Add SAL_ENABLE_GLYPH_CACHING
    
    Change-Id: I59dbfea2230012447732d12f732ad160a30908e7
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/README.vars b/vcl/README.vars
new file mode 100644
index 0000000..2749d869
--- /dev/null
+++ b/vcl/README.vars
@@ -0,0 +1,23 @@
+Environment variables in VCL:
+
+General
+-------
+SAL_USE_VCLPLUGIN - use a VCL plugin
+SAL_NO_NWF - disable native widgets
+SAL_FORCEDPI - force a specific DPI (gtk & gtk3 plugins only)
+
+VCL_DOUBLEBUFFERING_AVOID_PAINT - don't paint the buffer, useful to see where we do direct painting
+VCL_DOUBLEBUFFERING_FORCE_ENABLE - enable double buffered painting
+
+VCL_HIDE_WINDOWS - don't draw windows
+
+Bitmap
+------
+VCL_NO_THREAD_SCALE - disable threaded bitmap scale
+EMF_PLUS_DISABLE - use EMF rendering and ignore EMF+ specifics
+
+OpenGL
+------
+SAL_FORCEGL - force enable OpenGL
+SAL_WITHOUT_WIDGET_CACHE - disable LRU caching of native widget texutres
+SAL_ENABLE_GLYPH_CACHING - render glyphs to textures and use those, Windows only, WIP, broken
commit 605b0123f0a6cfa6502709adf2f35dab712a81e9
Author: Tor Lillqvist <tml at collabora.com>
Date:   Wed Aug 19 09:18:37 2015 +0300

    More fixing of glyph rendering for caching with OpenGL on Windows
    
    Change-Id: I934ad7453f35909f4c3ad999e33453b5b6032480
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 0ab9cd9..7f4c4a4 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -160,7 +160,10 @@ inline std::basic_ostream<charT, traits> & operator <<(
     stream << "{";
     for (auto i = rCache.cbegin(); i != rCache.cend(); ++i)
     {
-        stream << "[" << i->mnFirstGlyph << ".." << (i->mnFirstGlyph + i->mnGlyphCount - 1) << "]";
+        stream << "[" << i->mnFirstGlyph;
+        if (i->mnGlyphCount > 1)
+            stream << ".." << (i->mnFirstGlyph + i->mnGlyphCount - 1);
+        stream << "]";
         if (i+1 != rCache.cend())
         {
             stream << ",";
@@ -278,10 +281,16 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
     int totWidth = 0;
     for (int i = 0; i < nCount; i++)
     {
-        aDX[i] = std::abs(aABC[i].abcA) + aABC[i].abcB + std::abs(aABC[i].abcC);
+        aDX[i] = aABC[i].abcB + std::abs(aABC[i].abcC);
+        if (i == 0)
+            aDX[0] += std::abs(aABC[0].abcA);
+        if (i < nCount-1)
+            aDX[i] += std::abs(aABC[i+1].abcA);
         totWidth += aDX[i];
     }
 
+    SAL_INFO("vcl.gdi.opengl", "aSize=(" << aSize.cx << "," << aSize.cy << ") totWidth=" << totWidth);
+
     if (SelectObject(hDC, hOrigFont) == NULL)
         SAL_WARN("vcl.gdi", "SelectObject failed: " << WindowsErrorString(GetLastError()));
     if (!DeleteDC(hDC))
commit 33d8dae5fc827b20c85536d6dd20a6ce8012c1ac
Author: Tor Lillqvist <tml at collabora.com>
Date:   Tue Aug 18 13:43:27 2015 +0300

    More fixing of OpenGL glyph caching on Windows
    
    Now text looks better, for instance the lower-case "t" glyphs on the
    Start Centre aren't totally weird any more. But for instance the tip
    of the hook of "j" leaks into the "i" texture. I guess I really would
    need to render glyphs one by one.
    
    Change-Id: I69ae2d2f7c559530bcfdfc1a4915503fcb3ab4af
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index e32b8b5..0ab9cd9 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -204,7 +204,7 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
     if (nGlyphIndex == DROPPED_OUTGLYPH)
         return true;
 
-    SAL_INFO("vcl.gdi.opengl", "AddChunkOfGlyphs " << this << " " << nGlyphIndex << " old: " << maOpenGLGlyphCache);
+    SAL_INFO("vcl.gdi.opengl", "this=" << this << " " << nGlyphIndex << " old: " << maOpenGLGlyphCache);
 
     auto n = maOpenGLGlyphCache.begin();
     while (n != maOpenGLGlyphCache.end() &&
@@ -262,12 +262,32 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
         return false;
     }
 
+    std::vector<ABC> aABC(nCount);
+    if (!GetCharABCWidthsI(hDC, 0, nCount, aGlyphIndices.data(), aABC.data()))
+    {
+        SAL_WARN("vcl.gdi", "GetCharABCWidthsI failed: " << WindowsErrorString(GetLastError()));
+        return false;
+    }
+
+    for (int i = 0; i < nCount; i++)
+        std::cerr << aABC[i].abcA << ":" << aABC[i].abcB << ":" << aABC[i].abcC << " ";
+    std::cerr << std::endl;
+
+    // Avoid kerning as we want to be able to use individual rectangles for each glyph
+    std::vector<int> aDX(nCount);
+    int totWidth = 0;
+    for (int i = 0; i < nCount; i++)
+    {
+        aDX[i] = std::abs(aABC[i].abcA) + aABC[i].abcB + std::abs(aABC[i].abcC);
+        totWidth += aDX[i];
+    }
+
     if (SelectObject(hDC, hOrigFont) == NULL)
         SAL_WARN("vcl.gdi", "SelectObject failed: " << WindowsErrorString(GetLastError()));
     if (!DeleteDC(hDC))
         SAL_WARN("vcl.gdi", "DeleteDC failed: " << WindowsErrorString(GetLastError()));
 
-    OpenGLCompatibleDC aDC(rGraphics, 0, 0, aSize.cx, aSize.cy);
+    OpenGLCompatibleDC aDC(rGraphics, 0, 0, totWidth, aSize.cy);
 
     hOrigFont = SelectFont(aDC.getCompatibleHDC(), rLayout.mhFont);
     if (hOrigFont == NULL)
@@ -279,21 +299,6 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
     SetTextColor(aDC.getCompatibleHDC(), RGB(0, 0, 0));
     SetBkColor(aDC.getCompatibleHDC(), RGB(255, 255, 255));
 
-    std::vector<ABC> aABC(nCount);
-    if (!GetCharABCWidthsI(aDC.getCompatibleHDC(), 0, nCount, aGlyphIndices.data(), aABC.data()))
-    {
-        SAL_WARN("vcl.gdi", "GetCharABCWidthsI failed: " << WindowsErrorString(GetLastError()));
-        return false;
-    }
-
-    for (int i = 0; i < nCount; i++)
-        std::cerr << aABC[i].abcA << ":" << aABC[i].abcB << ":" << aABC[i].abcC << " ";
-    std::cerr << std::endl;
-
-    // Avoid kerning as we want to be able to use individual rectangles for each glyph
-    std::vector<int> aDX(nCount);
-    for (int i = 0; i < nCount; i++)
-        aDX[i] = std::abs(aABC[i].abcA) + aABC[i].abcB + std::abs(aABC[i].abcC);
     if (!ExtTextOutW(aDC.getCompatibleHDC(), 0, 0, ETO_GLYPH_INDEX, NULL, aGlyphIndices.data(), nCount, aDX.data()))
     {
         SAL_WARN("vcl.gdi", "ExtTextOutW failed: " << WindowsErrorString(GetLastError()));
@@ -317,7 +322,7 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
 
     SelectFont(aDC.getCompatibleHDC(), hOrigFont);
 
-    SAL_INFO("vcl.gdi.opengl", "AddChunkOfGlyphs " << this << " now: " << maOpenGLGlyphCache << DumpGlyphBitmap(aChunk, aDC.getCompatibleHDC()));
+    SAL_INFO("vcl.gdi.opengl", "this=" << this << " now: " << maOpenGLGlyphCache << DumpGlyphBitmap(aChunk, aDC.getCompatibleHDC()));
 
     return true;
 }
commit 3067f78aed31636e2eb955f55f099471cc8a4bf7
Author: Tor Lillqvist <tml at collabora.com>
Date:   Mon Aug 17 18:23:11 2015 +0300

    Add FIXME comment and bin an #if 0 snippet
    
    Change-Id: I0bbea4ef62c8e94d8b8f1bfb440712da5839e532
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 6f8b4ca..e32b8b5 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -1579,6 +1579,8 @@ bool UniscribeLayout::DrawCachedGlyphs(SalGraphics& rGraphics) const
 
     pImpl->PreDraw();
 
+    // FIXME: This code snippet is mostly copied from the one in
+    // UniscribeLayout::DrawTextImpl. Should be factored out.
     int nBaseClusterOffset = 0;
     int nBaseGlyphPos = -1;
     for( int nItem = 0; nItem < mnItemCount; ++nItem )
@@ -1626,16 +1628,6 @@ bool UniscribeLayout::DrawCachedGlyphs(SalGraphics& rGraphics) const
             pImpl->DrawMask(*rChunk.mpTexture, salColor, a2Rects);
             nAdvance += mpGlyphAdvances[i];
         }
-#if 0
-        ScriptTextOut(hDC, &rScriptCache,
-            aPos.X(), aPos.Y(), 0, NULL,
-            &rVisualItem.mpScriptItem->a, NULL, 0,
-            mpOutGlyphs + nMinGlyphPos,
-            nEndGlyphPos - nMinGlyphPos,
-            mpGlyphAdvances + nMinGlyphPos,
-            mpJustifications ? mpJustifications + nMinGlyphPos : NULL,
-            mpGlyphOffsets + nMinGlyphPos);
-#endif
     }
     pImpl->PostDraw();
 
commit a1ccba3f04db8c9e356d6973b6a02a5d511773b8
Author: Tor Lillqvist <tml at collabora.com>
Date:   Mon Aug 17 17:02:35 2015 +0300

    (disabled) Initial work for OpenGL glyph caching on Windows
    
    Shows text roughly correctly, but many problems. Conditional at
    run-time on the SAL_ENABLE_GLYPH_CACHING environment variable in
    addition to SAL_FORCEGL.
    
    One obvious thing that needs fixing is making sure that the glyphs are
    rendered into the texture without overlap. Compensating negative
    values in the ABC::abcA and ABC::abdC width is not enough.
    
    Also, the cache should be changed to actually have "cache"
    functionality, i.e. entries should expire based on some criterion.
    
    Change-Id: I66a37d3354a09011a654f15a7d2bd8efaa14ad1e
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index 236371c..a700fac 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -187,6 +187,7 @@ class WinSalGraphics : public SalGraphics
     friend class ScopedFont;
     friend class OpenGLCompatibleDC;
     friend class WinLayout;
+    friend class UniscribeLayout;
 
 protected:
     std::unique_ptr<SalGraphicsImpl> mpImpl;
diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 89503f3..6f8b4ca 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -22,6 +22,8 @@
 #include "osl/module.h"
 #include "osl/file.h"
 
+#include <comphelper/windowserrorstring.hxx>
+
 #include <opengl/texture.hxx>
 #include <opengl/win/gdiimpl.hxx>
 #include <vcl/opengl/OpenGLHelper.hxx>
@@ -32,6 +34,8 @@
 #include "sallayout.hxx"
 
 #include <cstdio>
+#include <cstdlib>
+
 #include <sal/alloca.h>
 
 #include <algorithm>
@@ -54,6 +58,14 @@ typedef std::unordered_map<int,int> IntMap;
 
 #include <config_mingw.h>
 
+struct OpenGLGlyphCacheChunk
+{
+    WORD mnFirstGlyph;
+    int mnGlyphCount;
+    std::vector<Rectangle> maLocation;
+    std::shared_ptr<OpenGLTexture> mpTexture;
+};
+
 // win32 specific physical font instance
 class ImplWinFontEntry : public ImplFontEntry
 {
@@ -77,6 +89,7 @@ public:
                             { return maScriptCache; }
 private:
     mutable SCRIPT_CACHE    maScriptCache;
+    std::vector<OpenGLGlyphCacheChunk> maOpenGLGlyphCache;
 
 public:
     int                     GetCachedGlyphWidth( int nCharCode ) const;
@@ -90,8 +103,74 @@ private:
     IntMap                  maWidthMap;
     mutable int             mnMinKashidaWidth;
     mutable int             mnMinKashidaGlyph;
+
+public:
+    bool                    GlyphIsCached(int nGlyphIndex) const;
+    bool                    AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayout, SalGraphics& rGraphics);
+    const OpenGLGlyphCacheChunk&  GetCachedGlyphChunkFor(int nGlyphIndex) const;
 };
 
+char ColorFor(COLORREF aColor)
+{
+    if (aColor == RGB(0xFF, 0xFF, 0xFF))
+        return ' ';
+    return '0' + 10*((GetRValue(aColor) + GetGValue(aColor) + GetBValue(aColor)) / (0xFF*3));
+}
+
+OUString DumpGlyphBitmap(OpenGLGlyphCacheChunk& rChunk, HDC hDC)
+{
+    HBITMAP hBitmap = static_cast<HBITMAP>(GetCurrentObject(hDC, OBJ_BITMAP));
+    if (hBitmap == NULL)
+    {
+        SAL_WARN("vcl.gdi", "GetCurrentObject failed: " << WindowsErrorString(GetLastError()));
+        return "";
+    }
+
+    BITMAP aBitmap;
+    if (!GetObjectW(hBitmap, sizeof(aBitmap), &aBitmap))
+    {
+        SAL_WARN("vcl.gdi", "GetObjectW failed: " << WindowsErrorString(GetLastError()));
+        return "";
+    }
+
+    std::cerr << "Bitmap " << hBitmap << ": " << aBitmap.bmWidth << "x" << aBitmap.bmHeight << ":" << std::endl;
+    int nPos = 0;
+    for (int i = 1; i < rChunk.mnGlyphCount && nPos < 75; i++)
+    {
+        for (int j = nPos; j < rChunk.maLocation[i].Left(); j++)
+            std::cerr << " ";
+        std::cerr << "!";
+        nPos = rChunk.maLocation[i].Left() + 1;
+    }
+    std::cerr << std::endl;
+
+    for (long y = 0; y < std::min(20l, aBitmap.bmHeight); y++)
+    {
+        for (long x = 0; x < std::min(75l, aBitmap.bmWidth); x++)
+            std::cerr << ColorFor(GetPixel(hDC, x, y));
+        std::cerr << std::endl;
+    }
+    return "";
+}
+
+template< typename charT, typename traits >
+inline std::basic_ostream<charT, traits> & operator <<(
+    std::basic_ostream<charT, traits> & stream, const std::vector<OpenGLGlyphCacheChunk>& rCache )
+{
+    stream << "{";
+    for (auto i = rCache.cbegin(); i != rCache.cend(); ++i)
+    {
+        stream << "[" << i->mnFirstGlyph << ".." << (i->mnFirstGlyph + i->mnGlyphCount - 1) << "]";
+        if (i+1 != rCache.cend())
+        {
+            stream << ",";
+            assert(i->mnFirstGlyph + i->mnGlyphCount <= (i+1)->mnFirstGlyph);
+        }
+    }
+
+    return stream << "}";
+}
+
 inline void ImplWinFontEntry::CacheGlyphWidth( int nCharCode, int nCharWidth )
 {
     maWidthMap[ nCharCode ] = nCharWidth;
@@ -105,6 +184,154 @@ inline int ImplWinFontEntry::GetCachedGlyphWidth( int nCharCode ) const
     return it->second;
 }
 
+bool ImplWinFontEntry::GlyphIsCached(int nGlyphIndex) const
+{
+    if (nGlyphIndex == DROPPED_OUTGLYPH)
+        return true;
+
+    for (size_t i = 0; i < maOpenGLGlyphCache.size(); i++)
+        if (nGlyphIndex >= maOpenGLGlyphCache[i].mnFirstGlyph &&
+            nGlyphIndex < maOpenGLGlyphCache[i].mnFirstGlyph + maOpenGLGlyphCache[i].mnGlyphCount)
+            return true;
+
+    return false;
+}
+
+bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayout, SalGraphics& rGraphics)
+{
+    const int DEFAULT_CHUNK_SIZE = 20;
+
+    if (nGlyphIndex == DROPPED_OUTGLYPH)
+        return true;
+
+    SAL_INFO("vcl.gdi.opengl", "AddChunkOfGlyphs " << this << " " << nGlyphIndex << " old: " << maOpenGLGlyphCache);
+
+    auto n = maOpenGLGlyphCache.begin();
+    while (n != maOpenGLGlyphCache.end() &&
+           nGlyphIndex > n->mnFirstGlyph)
+        ++n;
+    assert(n == maOpenGLGlyphCache.end() || nGlyphIndex < n->mnFirstGlyph);
+
+    int nCount = DEFAULT_CHUNK_SIZE;
+    if (n != maOpenGLGlyphCache.end() && nGlyphIndex + nCount >= n->mnFirstGlyph)
+        nCount = n->mnFirstGlyph - nGlyphIndex;
+
+    if (nCount < DEFAULT_CHUNK_SIZE)
+    {
+        if (n == maOpenGLGlyphCache.begin())
+        {
+            nGlyphIndex = std::max(0, n->mnFirstGlyph - DEFAULT_CHUNK_SIZE);
+        }
+        else
+        {
+            nGlyphIndex = std::max(n[-1].mnFirstGlyph + n[-1].mnGlyphCount,
+                                   n->mnFirstGlyph - DEFAULT_CHUNK_SIZE);
+        }
+        nCount = n->mnFirstGlyph - nGlyphIndex;
+    }
+
+    OpenGLGlyphCacheChunk aChunk;
+    aChunk.mnFirstGlyph = nGlyphIndex;
+    aChunk.mnGlyphCount = nCount;
+
+    std::vector<WORD> aGlyphIndices(nCount);
+    for (int i = 0; i < nCount; i++)
+        aGlyphIndices[i] = nGlyphIndex + i;
+
+    HDC hDC = CreateCompatibleDC(rLayout.mhDC);
+    if (hDC == NULL)
+    {
+        SAL_WARN("vcl.gdi", "CreateCompatibleDC failed: " << WindowsErrorString(GetLastError()));
+        return false;
+    }
+    HFONT hOrigFont = static_cast<HFONT>(SelectObject(hDC, rLayout.mhFont));
+    if (hOrigFont == NULL)
+    {
+        SAL_WARN("vcl.gdi", "SelectObject failed: " << WindowsErrorString(GetLastError()));
+        DeleteDC(hDC);
+        return false;
+    }
+
+    SIZE aSize;
+
+    if (!GetTextExtentExPointI(hDC, aGlyphIndices.data(), nCount, 0, NULL, NULL, &aSize))
+    {
+        SAL_WARN("vcl.gdi", "GetTextExtentExPointI failed: " << WindowsErrorString(GetLastError()));
+        SelectObject(hDC, hOrigFont);
+        DeleteDC(hDC);
+        return false;
+    }
+
+    if (SelectObject(hDC, hOrigFont) == NULL)
+        SAL_WARN("vcl.gdi", "SelectObject failed: " << WindowsErrorString(GetLastError()));
+    if (!DeleteDC(hDC))
+        SAL_WARN("vcl.gdi", "DeleteDC failed: " << WindowsErrorString(GetLastError()));
+
+    OpenGLCompatibleDC aDC(rGraphics, 0, 0, aSize.cx, aSize.cy);
+
+    hOrigFont = SelectFont(aDC.getCompatibleHDC(), rLayout.mhFont);
+    if (hOrigFont == NULL)
+    {
+        SAL_WARN("vcl.gdi", "SelectObject failed: " << WindowsErrorString(GetLastError()));
+        return false;
+    }
+
+    SetTextColor(aDC.getCompatibleHDC(), RGB(0, 0, 0));
+    SetBkColor(aDC.getCompatibleHDC(), RGB(255, 255, 255));
+
+    std::vector<ABC> aABC(nCount);
+    if (!GetCharABCWidthsI(aDC.getCompatibleHDC(), 0, nCount, aGlyphIndices.data(), aABC.data()))
+    {
+        SAL_WARN("vcl.gdi", "GetCharABCWidthsI failed: " << WindowsErrorString(GetLastError()));
+        return false;
+    }
+
+    for (int i = 0; i < nCount; i++)
+        std::cerr << aABC[i].abcA << ":" << aABC[i].abcB << ":" << aABC[i].abcC << " ";
+    std::cerr << std::endl;
+
+    // Avoid kerning as we want to be able to use individual rectangles for each glyph
+    std::vector<int> aDX(nCount);
+    for (int i = 0; i < nCount; i++)
+        aDX[i] = std::abs(aABC[i].abcA) + aABC[i].abcB + std::abs(aABC[i].abcC);
+    if (!ExtTextOutW(aDC.getCompatibleHDC(), 0, 0, ETO_GLYPH_INDEX, NULL, aGlyphIndices.data(), nCount, aDX.data()))
+    {
+        SAL_WARN("vcl.gdi", "ExtTextOutW failed: " << WindowsErrorString(GetLastError()));
+        return false;
+    }
+
+    aChunk.maLocation.resize(nCount);
+    UINT nPos = 0;
+    for (int i = 0; i < nCount; i++)
+    {
+        aChunk.maLocation[i].Left() = nPos;
+        aChunk.maLocation[i].Right() = nPos + aDX[i];
+        nPos = aChunk.maLocation[i].Right();
+        aChunk.maLocation[i].Top() = 0;
+        aChunk.maLocation[i].Bottom() = aSize.cy;
+    }
+
+    aChunk.mpTexture = std::unique_ptr<OpenGLTexture>(aDC.getTexture());
+
+    maOpenGLGlyphCache.insert(n, aChunk);
+
+    SelectFont(aDC.getCompatibleHDC(), hOrigFont);
+
+    SAL_INFO("vcl.gdi.opengl", "AddChunkOfGlyphs " << this << " now: " << maOpenGLGlyphCache << DumpGlyphBitmap(aChunk, aDC.getCompatibleHDC()));
+
+    return true;
+}
+
+const OpenGLGlyphCacheChunk& ImplWinFontEntry::GetCachedGlyphChunkFor(int nGlyphIndex) const
+{
+    auto i = maOpenGLGlyphCache.cbegin();
+    while (i != maOpenGLGlyphCache.cend() && nGlyphIndex >= i->mnFirstGlyph + i->mnGlyphCount)
+        ++i;
+    assert(i != maOpenGLGlyphCache.cend());
+    assert(nGlyphIndex >= i->mnFirstGlyph && nGlyphIndex < i->mnFirstGlyph + i->mnGlyphCount);
+    return *i;
+}
+
 WinLayout::WinLayout(HDC hDC, const ImplWinFontData& rWFD, ImplWinFontEntry& rWFE, bool bUseOpenGL)
 :   mhDC( hDC ),
     mhFont( (HFONT)GetCurrentObject(hDC,OBJ_FONT) ),
@@ -157,6 +384,11 @@ void WinLayout::DrawText(SalGraphics& rGraphics) const
         // no OpenGL, just classic rendering
         DrawTextImpl(hDC);
     }
+    else if (CacheGlyphs(rGraphics) &&
+             DrawCachedGlyphs(rGraphics))
+    {
+        // Nothing
+    }
     else
     {
         // We have to render the text to a hidden texture, and draw it.
@@ -1311,6 +1543,105 @@ void UniscribeLayout::DrawTextImpl(HDC hDC) const
         DeleteFont(SelectFont(hDC, hOrigFont));
 }
 
+bool UniscribeLayout::CacheGlyphs(SalGraphics& rGraphics) const
+{
+    const bool bDoGlyphCaching = (std::getenv("SAL_ENABLE_GLYPH_CACHING") != NULL);
+
+    if (!bDoGlyphCaching)
+        return false;
+
+    for (int i = 0; i < mnGlyphCount; i++)
+    {
+        if (mrWinFontEntry.GlyphIsCached(mpOutGlyphs[i]))
+            continue;
+
+        if (!mrWinFontEntry.AddChunkOfGlyphs(mpOutGlyphs[i], *this, rGraphics))
+            return false;
+    }
+
+    return true;
+}
+
+bool UniscribeLayout::DrawCachedGlyphs(SalGraphics& rGraphics) const
+{
+    WinSalGraphics& rWinGraphics = static_cast<WinSalGraphics&>(rGraphics);
+    HDC hDC = rWinGraphics.getHDC();
+
+    Rectangle aRect;
+    GetBoundRect(rGraphics, aRect);
+
+    COLORREF color = GetTextColor(hDC);
+    SalColor salColor = MAKE_SALCOLOR(GetRValue(color), GetGValue(color), GetBValue(color));
+
+    WinOpenGLSalGraphicsImpl *pImpl = dynamic_cast<WinOpenGLSalGraphicsImpl*>(rWinGraphics.mpImpl.get());
+    if (!pImpl)
+        return false;
+
+    pImpl->PreDraw();
+
+    int nBaseClusterOffset = 0;
+    int nBaseGlyphPos = -1;
+    for( int nItem = 0; nItem < mnItemCount; ++nItem )
+    {
+        const VisualItem& rVisualItem = mpVisualItems[ nItem ];
+
+        // skip if there is nothing to display
+        int nMinGlyphPos, nEndGlyphPos;
+        if( !GetItemSubrange( rVisualItem, nMinGlyphPos, nEndGlyphPos ) )
+            continue;
+
+        if( nBaseGlyphPos < 0 )
+        {
+            // adjust draw position relative to cluster start
+            if( rVisualItem.IsRTL() )
+                nBaseGlyphPos = nEndGlyphPos - 1;
+            else
+                nBaseGlyphPos = nMinGlyphPos;
+
+            int i = mnMinCharPos;
+            while( (--i >= rVisualItem.mnMinCharPos)
+                && (nBaseGlyphPos == mpLogClusters[i]) )
+                 nBaseClusterOffset += mpCharWidths[i];
+
+            if( !rVisualItem.IsRTL() )
+                nBaseClusterOffset = -nBaseClusterOffset;
+        }
+
+        // now draw the matching glyphs in this item
+        Point aRelPos( rVisualItem.mnXOffset + nBaseClusterOffset, 0 );
+        Point aPos = GetDrawPosition( aRelPos );
+
+        int nAdvance = 0;
+        for (int i = nMinGlyphPos; i < nEndGlyphPos; i++)
+        {
+            assert(mrWinFontEntry.GlyphIsCached(mpOutGlyphs[i]));
+
+            const OpenGLGlyphCacheChunk& rChunk = mrWinFontEntry.GetCachedGlyphChunkFor(mpOutGlyphs[i]);
+            const int n = mpOutGlyphs[i] - rChunk.mnFirstGlyph;
+
+            SalTwoRect a2Rects(rChunk.maLocation[n].Left(), rChunk.maLocation[n].Top(),
+                               rChunk.maLocation[n].GetWidth(), rChunk.maLocation[n].GetHeight(),
+                               nAdvance + aPos.X() + mpGlyphOffsets[i].du, aPos.Y() + mpGlyphOffsets[i].dv - rChunk.maLocation[n].GetHeight(),
+                               rChunk.maLocation[n].GetWidth(), rChunk.maLocation[n].GetHeight()); // ???
+            pImpl->DrawMask(*rChunk.mpTexture, salColor, a2Rects);
+            nAdvance += mpGlyphAdvances[i];
+        }
+#if 0
+        ScriptTextOut(hDC, &rScriptCache,
+            aPos.X(), aPos.Y(), 0, NULL,
+            &rVisualItem.mpScriptItem->a, NULL, 0,
+            mpOutGlyphs + nMinGlyphPos,
+            nEndGlyphPos - nMinGlyphPos,
+            mpGlyphAdvances + nMinGlyphPos,
+            mpJustifications ? mpJustifications + nMinGlyphPos : NULL,
+            mpGlyphOffsets + nMinGlyphPos);
+#endif
+    }
+    pImpl->PostDraw();
+
+    return true;
+}
+
 DeviceCoordinate UniscribeLayout::FillDXArray( DeviceCoordinate* pDXArray ) const
 {
     // calculate width of the complete layout
@@ -1954,6 +2285,16 @@ void GraphiteWinLayout::DrawTextImpl(HDC hDC) const
         DeleteFont(SelectFont(hDC, hOrigFont));
 }
 
+bool GraphiteWinLayout::CacheGlyphs(SalGraphics& /*rGraphics*/) const
+{
+    return false;
+}
+
+bool GraphiteWinLayout::DrawCachedGlyphs(SalGraphics& /*rGraphics*/) const
+{
+    return false;
+}
+
 sal_Int32 GraphiteWinLayout::GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const
 {
     sal_Int32 nBreak = maImpl.GetTextBreak(nMaxWidth, nCharExtra, nFactor);
diff --git a/vcl/win/source/gdi/winlayout.hxx b/vcl/win/source/gdi/winlayout.hxx
index 7819eae..8855e37 100644
--- a/vcl/win/source/gdi/winlayout.hxx
+++ b/vcl/win/source/gdi/winlayout.hxx
@@ -54,7 +54,9 @@ public:
     /// Draw to the provided HDC.
     virtual void        DrawTextImpl(HDC hDC) const = 0;
 
-protected:
+    virtual bool        CacheGlyphs(SalGraphics& rGraphics) const = 0;
+    virtual bool        DrawCachedGlyphs(SalGraphics& rGraphics) const = 0;
+
     HDC                 mhDC;               // WIN32 device handle
     HFONT               mhFont;             // WIN32 font handle
     int                 mnBaseAdv;          // x-offset relative to Layout origin
@@ -73,6 +75,8 @@ public:
     virtual bool    LayoutText( ImplLayoutArgs& ) SAL_OVERRIDE;
     virtual void    AdjustLayout( ImplLayoutArgs& ) SAL_OVERRIDE;
     virtual void    DrawTextImpl(HDC hDC) const SAL_OVERRIDE;
+    virtual bool    CacheGlyphs(SalGraphics& rGraphics) const SAL_OVERRIDE;
+    virtual bool    DrawCachedGlyphs(SalGraphics& rGraphics) const SAL_OVERRIDE;
     virtual int     GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos, int&,
                                    DeviceCoordinate* pGlyphAdvances, int* pCharPosAry,
                                    const PhysicalFontFace** pFallbackFonts = NULL ) const SAL_OVERRIDE;
@@ -160,6 +164,8 @@ public:
     virtual bool  LayoutText( ImplLayoutArgs& ) SAL_OVERRIDE;    // first step of layout
     virtual void  AdjustLayout( ImplLayoutArgs& ) SAL_OVERRIDE;  // adjusting after fallback etc.
     virtual void  DrawTextImpl(HDC hDC) const SAL_OVERRIDE;
+    virtual bool  CacheGlyphs(SalGraphics& rGraphics) const SAL_OVERRIDE;
+    virtual bool  DrawCachedGlyphs(SalGraphics& rGraphics) const SAL_OVERRIDE;
 
     // methods using string indexing
     virtual sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra=0, int nFactor=1) const SAL_OVERRIDE;
commit 67ccc383c34996e958f6824dea1283c98886689d
Author: Tor Lillqvist <tml at collabora.com>
Date:   Thu Aug 13 13:22:28 2015 +0300

    Add a globally usable WindowsErrorString function
    
    Is comphelper the right place for this? Is having it as "inline" the right
    way?
    
    Change-Id: I973dbde108f89b6cab17e5d88db2390d6f18a672
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/include/comphelper/windowserrorstring.hxx b/include/comphelper/windowserrorstring.hxx
new file mode 100644
index 0000000..1da7e9c
--- /dev/null
+++ b/include/comphelper/windowserrorstring.hxx
@@ -0,0 +1,46 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_COMPHELPER_WINDOWSERRORSTRING_HXX
+#define INCLUDED_COMPHELPER_WINDOWSERRORSTRING_HXX
+
+#include <prewin.h>
+#include <postwin.h>
+#include <rtl/ustring.hxx>
+
+namespace {
+
+inline OUString WindowsErrorString(DWORD nErrorCode)
+{
+    LPWSTR pMsgBuf;
+
+    if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
+                       NULL,
+                       nErrorCode,
+                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                       (LPWSTR)&pMsgBuf,
+                       0,
+                       NULL) == 0)
+        return OUString::number(nErrorCode, 16);
+
+    if (pMsgBuf[wcslen(pMsgBuf)-1] == '\n')
+        pMsgBuf[wcslen(pMsgBuf)-1] = '\0';
+
+    OUString result(pMsgBuf);
+
+    LocalFree(pMsgBuf);
+
+    return result;
+}
+
+} // anonymous namespace
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/source/gdi/pdfwriter_impl.cxx b/vcl/source/gdi/pdfwriter_impl.cxx
index db66f60..f6ff40f 100644
--- a/vcl/source/gdi/pdfwriter_impl.cxx
+++ b/vcl/source/gdi/pdfwriter_impl.cxx
@@ -92,6 +92,7 @@
 #include <prewin.h>
 #include <wincrypt.h>
 #include <postwin.h>
+#include <comphelper/windowserrorstring.hxx>
 #endif
 
 #include <config_eot.h>
@@ -6761,33 +6762,6 @@ typedef BOOL (WINAPI *PointerTo_CryptRetrieveTimeStamp)(LPCWSTR wszUrl,
                                                         PCCERT_CONTEXT *ppTsSigner,
                                                         HCERTSTORE phStore);
 
-namespace {
-
-OUString WindowsError(DWORD nErrorCode)
-{
-    LPWSTR pMsgBuf;
-
-    if (FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
-                       NULL,
-                       nErrorCode,
-                       MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
-                       (LPWSTR)&pMsgBuf,
-                       0,
-                       NULL) == 0)
-        return OUString::number(nErrorCode, 16);
-
-    if (pMsgBuf[wcslen(pMsgBuf)-1] == '\n')
-        pMsgBuf[wcslen(pMsgBuf)-1] = '\0';
-
-    OUString result(pMsgBuf);
-
-    LocalFree(pMsgBuf);
-
-    return result;
-}
-
-}
-
 #endif
 
 bool PDFWriterImpl::finalizeSignature()
@@ -7286,7 +7260,7 @@ bool PDFWriterImpl::finalizeSignature()
     PCCERT_CONTEXT pCertContext = CertCreateCertificateContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, reinterpret_cast<const BYTE*>(n_derArray), n_derLength);
     if (pCertContext == NULL)
     {
-        SAL_WARN("vcl.pdfwriter", "CertCreateCertificateContext failed: " << WindowsError(GetLastError()));
+        SAL_WARN("vcl.pdfwriter", "CertCreateCertificateContext failed: " << WindowsErrorString(GetLastError()));
         return false;
     }
 
@@ -7312,7 +7286,7 @@ bool PDFWriterImpl::finalizeSignature()
                                            &nKeySpec,
                                            &bFreeNeeded))
     {
-        SAL_WARN("vcl.pdfwriter", "CryptAcquireCertificatePrivateKey failed: " << WindowsError(GetLastError()));
+        SAL_WARN("vcl.pdfwriter", "CryptAcquireCertificatePrivateKey failed: " << WindowsErrorString(GetLastError()));
         CertFreeCertificateContext(pCertContext);
         return false;
     }
@@ -7350,7 +7324,7 @@ bool PDFWriterImpl::finalizeSignature()
                                       NULL,
                                       NULL)))
     {
-        SAL_WARN("vcl.pdfwriter", "CryptMsgOpenToEncode failed: " << WindowsError(GetLastError()));
+        SAL_WARN("vcl.pdfwriter", "CryptMsgOpenToEncode failed: " << WindowsErrorString(GetLastError()));
         CertFreeCertificateContext(pCertContext);
         return false;
     }
@@ -7358,7 +7332,7 @@ bool PDFWriterImpl::finalizeSignature()
     if (!CryptMsgUpdate(hMsg, (const BYTE *)buffer1.get(), bytesRead1, FALSE) ||
         !CryptMsgUpdate(hMsg, (const BYTE *)buffer2.get(), bytesRead2, TRUE))
     {
-        SAL_WARN("vcl.pdfwriter", "CryptMsgUpdate failed: " << WindowsError(GetLastError()));
+        SAL_WARN("vcl.pdfwriter", "CryptMsgUpdate failed: " << WindowsErrorString(GetLastError()));
         CryptMsgClose(hMsg);
         CertFreeCertificateContext(pCertContext);
         return false;
@@ -7371,7 +7345,7 @@ bool PDFWriterImpl::finalizeSignature()
         PointerTo_CryptRetrieveTimeStamp crts = (PointerTo_CryptRetrieveTimeStamp) GetProcAddress(LoadLibrary("crypt32.dll"), "CryptRetrieveTimeStamp");
         if (!crts)
         {
-            SAL_WARN("vcl.pdfwriter", "Could not find the CryptRetrieveTimeStamp function in crypt32.dll: " << WindowsError(GetLastError()));
+            SAL_WARN("vcl.pdfwriter", "Could not find the CryptRetrieveTimeStamp function in crypt32.dll: " << WindowsErrorString(GetLastError()));
             CryptMsgClose(hMsg);
             CertFreeCertificateContext(pCertContext);
             return false;
@@ -7385,7 +7359,7 @@ bool PDFWriterImpl::finalizeSignature()
                                                  NULL,
                                                  NULL)))
         {
-            SAL_WARN("vcl.pdfwriter", "CryptMsgOpenToDecode failed: " << WindowsError(GetLastError()));
+            SAL_WARN("vcl.pdfwriter", "CryptMsgOpenToDecode failed: " << WindowsErrorString(GetLastError()));
             CryptMsgClose(hMsg);
             CertFreeCertificateContext(pCertContext);
             return false;
@@ -7395,7 +7369,7 @@ bool PDFWriterImpl::finalizeSignature()
 
         if (!CryptMsgGetParam(hMsg, CMSG_BARE_CONTENT_PARAM, 0, NULL, &nTsSigLen))
         {
-            SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_BARE_CONTENT_PARAM) failed: " << WindowsError(GetLastError()));
+            SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_BARE_CONTENT_PARAM) failed: " << WindowsErrorString(GetLastError()));
             CryptMsgClose(hDecodedMsg);
             CryptMsgClose(hMsg);
             CertFreeCertificateContext(pCertContext);
@@ -7408,7 +7382,7 @@ bool PDFWriterImpl::finalizeSignature()
 
         if (!CryptMsgGetParam(hMsg, CMSG_BARE_CONTENT_PARAM, 0, pTsSig.get(), &nTsSigLen))
         {
-            SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_BARE_CONTENT_PARAM) failed: " << WindowsError(GetLastError()));
+            SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_BARE_CONTENT_PARAM) failed: " << WindowsErrorString(GetLastError()));
             CryptMsgClose(hDecodedMsg);
             CryptMsgClose(hMsg);
             CertFreeCertificateContext(pCertContext);
@@ -7417,7 +7391,7 @@ bool PDFWriterImpl::finalizeSignature()
 
         if (!CryptMsgUpdate(hDecodedMsg, pTsSig.get(), nTsSigLen, TRUE))
         {
-            SAL_WARN("vcl.pdfwriter", "CryptMsgUpdate failed: " << WindowsError(GetLastError()));
+            SAL_WARN("vcl.pdfwriter", "CryptMsgUpdate failed: " << WindowsErrorString(GetLastError()));
             CryptMsgClose(hDecodedMsg);
             CryptMsgClose(hMsg);
             CertFreeCertificateContext(pCertContext);
@@ -7427,7 +7401,7 @@ bool PDFWriterImpl::finalizeSignature()
         DWORD nDecodedSignerInfoLen = 0;
         if (!CryptMsgGetParam(hDecodedMsg, CMSG_SIGNER_INFO_PARAM, 0, NULL, &nDecodedSignerInfoLen))
         {
-            SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) failed: " << WindowsError(GetLastError()));
+            SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) failed: " << WindowsErrorString(GetLastError()));
             CryptMsgClose(hDecodedMsg);
             CryptMsgClose(hMsg);
             CertFreeCertificateContext(pCertContext);
@@ -7438,7 +7412,7 @@ bool PDFWriterImpl::finalizeSignature()
 
         if (!CryptMsgGetParam(hDecodedMsg, CMSG_SIGNER_INFO_PARAM, 0, pDecodedSignerInfoBuf.get(), &nDecodedSignerInfoLen))
         {
-            SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) failed: " << WindowsError(GetLastError()));
+            SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_SIGNER_INFO_PARAM) failed: " << WindowsErrorString(GetLastError()));
             CryptMsgClose(hDecodedMsg);
             CryptMsgClose(hMsg);
             CertFreeCertificateContext(pCertContext);
@@ -7468,7 +7442,7 @@ bool PDFWriterImpl::finalizeSignature()
                      NULL,
                      NULL))
         {
-            SAL_WARN("vcl.pdfwriter", "CryptRetrieveTimeStamp failed: " << WindowsError(GetLastError()));
+            SAL_WARN("vcl.pdfwriter", "CryptRetrieveTimeStamp failed: " << WindowsErrorString(GetLastError()));
             CryptMsgClose(hDecodedMsg);
             CryptMsgClose(hMsg);
             CertFreeCertificateContext(pCertContext);
@@ -7514,7 +7488,7 @@ bool PDFWriterImpl::finalizeSignature()
             !CryptMsgUpdate(hMsg, (const BYTE *)buffer1.get(), bytesRead1, FALSE) ||
             !CryptMsgUpdate(hMsg, (const BYTE *)buffer2.get(), bytesRead2, TRUE))
         {
-            SAL_WARN("vcl.pdfwriter", "Re-creating the message failed: " << WindowsError(GetLastError()));
+            SAL_WARN("vcl.pdfwriter", "Re-creating the message failed: " << WindowsErrorString(GetLastError()));
             CryptMemFree(pTsContext);
             CryptMsgClose(hDecodedMsg);
             CryptMsgClose(hMsg);
@@ -7529,7 +7503,7 @@ bool PDFWriterImpl::finalizeSignature()
 
     if (!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, NULL, &nSigLen))
     {
-        SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_CONTENT_PARAM) failed: " << WindowsError(GetLastError()));
+        SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_CONTENT_PARAM) failed: " << WindowsErrorString(GetLastError()));
         if (pTsContext)
             CryptMemFree(pTsContext);
         CryptMsgClose(hMsg);
@@ -7552,7 +7526,7 @@ bool PDFWriterImpl::finalizeSignature()
 
     if (!CryptMsgGetParam(hMsg, CMSG_CONTENT_PARAM, 0, pSig.get(), &nSigLen))
     {
-        SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_CONTENT_PARAM) failed: " << WindowsError(GetLastError()));
+        SAL_WARN("vcl.pdfwriter", "CryptMsgGetParam(CMSG_CONTENT_PARAM) failed: " << WindowsErrorString(GetLastError()));
         if (pTsContext)
             CryptMemFree(pTsContext);
         CryptMsgClose(hMsg);
commit 633584e7395d06464ac58c8f94852be01bc29ce2
Author: Tor Lillqvist <tml at collabora.com>
Date:   Wed Aug 12 10:47:20 2015 +0300

    WaE: 'rArgs' : unreferenced formal parameter
    
    Change-Id: Ia41882a4d33e7b148044801902517b2b034d3ee4
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index ff7f853..89503f3 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -1995,7 +1995,7 @@ void GraphiteWinLayout::Simplify( bool is_base )
 }
 #endif // ENABLE_GRAPHITE
 
-SalLayout* WinSalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel )
+SalLayout* WinSalGraphics::GetTextLayout( ImplLayoutArgs& /*rArgs*/, int nFallbackLevel )
 {
     if (!mpWinFontEntry[nFallbackLevel]) return nullptr;
 
commit 1927a743755d8b3b55189b02a031b8cf90ba25ec
Author: Tor Lillqvist <tml at collabora.com>
Date:   Wed Aug 12 08:18:50 2015 +0300

    Drop SimpleWinLayout
    
    Use Uniscribe also for non-complex text. It is complicated enough to
    have separate Graphite and Uniscribe layout engines. Will make further
    changes to the code easier to manage, especially as with the
    UniscribeLayout code we have access to the actual
    glyphs. (Cf. 3e47219e06b9a279ba22a9bbef668731f2d3e07d)
    
    Change-Id: I9c67c172fe3e3d26d1c6cb1c0b7f1516b0b87f12
    Signed-off-by: Michael Meeks <michael.meeks at collabora.com>

diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx
index 9edf88c..ff7f853 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -228,694 +228,6 @@ void WinLayout::DrawText(SalGraphics& rGraphics) const
     }
 }
 
-SimpleWinLayout::SimpleWinLayout(HDC hDC, BYTE nCharSet, const ImplWinFontData& rWinFontData,
-        ImplWinFontEntry& rWinFontEntry, bool bUseOpenGL)
-:   WinLayout(hDC, rWinFontData, rWinFontEntry, bUseOpenGL),
-    mnGlyphCount( 0 ),
-    mnCharCount( 0 ),
-    mpOutGlyphs( NULL ),
-    mpGlyphAdvances( NULL ),
-    mpGlyphOrigAdvs( NULL ),
-    mpCharWidths( NULL ),
-    mpChars2Glyphs( NULL ),
-    mpGlyphs2Chars( NULL ),
-    mpGlyphRTLFlags( NULL ),
-    mnWidth( 0 ),
-    mnNotdefWidth( -1 ),
-    mnCharSet( nCharSet )
-{
-}
-
-SimpleWinLayout::~SimpleWinLayout()
-{
-    delete[] mpGlyphRTLFlags;
-    delete[] mpGlyphs2Chars;
-    delete[] mpChars2Glyphs;
-    if( mpCharWidths != mpGlyphAdvances )
-        delete[] mpCharWidths;
-    delete[] mpGlyphOrigAdvs;
-    delete[] mpGlyphAdvances;
-    delete[] mpOutGlyphs;
-}
-
-bool SimpleWinLayout::LayoutText( ImplLayoutArgs& rArgs )
-{
-    // prepare layout
-    // TODO: fix case when recyclying old SimpleWinLayout object
-    mnCharCount = rArgs.mnEndCharPos - rArgs.mnMinCharPos;
-
-    // TODO: use a cached value for bDisableAsianKern from upper layers
-    if( rArgs.mnFlags & SalLayoutFlags::KerningAsian )
-    {
-        TEXTMETRICA aTextMetricA;
-        if( GetTextMetricsA( mhDC, &aTextMetricA )
-        && !(aTextMetricA.tmPitchAndFamily & TMPF_FIXED_PITCH) && !(aTextMetricA.tmCharSet == 0x86) )
-            rArgs.mnFlags &= ~SalLayoutFlags::KerningAsian;
-    }
-
-    // layout text
-    int i, j;
-
-    mnGlyphCount = 0;
-    bool bVertical(rArgs.mnFlags & SalLayoutFlags::Vertical);
-
-    // count the number of chars to process if no RTL run
-    rArgs.ResetPos();
-    bool bHasRTL = false;
-    while( rArgs.GetNextRun( &i, &j, &bHasRTL ) && !bHasRTL )
-        mnGlyphCount += j - i;
-
-    // if there are RTL runs we need room to remember individual BiDi flags
-    if( bHasRTL )
-    {
-        mpGlyphRTLFlags = new bool[ mnCharCount ];
-        for( i = 0; i < mnCharCount; ++i )
-            mpGlyphRTLFlags[i] = false;
-    }
-
-    // rewrite the logical string if needed to prepare for the API calls
-    const sal_Unicode* pBidiStr = rArgs.mpStr + rArgs.mnMinCharPos;
-    if( (mnGlyphCount != mnCharCount) || bVertical )
-    {
-        // we need to rewrite the pBidiStr when any of
-        // - BiDirectional layout
-        // - vertical layout
-        // - partial runs (e.g. with control chars or for glyph fallback)
-        // are involved
-        sal_Unicode* pRewrittenStr = (sal_Unicode*)alloca( mnCharCount * sizeof(sal_Unicode) );
-        pBidiStr = pRewrittenStr;
-
-        // note: glyph to char mapping is relative to first character
-        mpChars2Glyphs = new int[ mnCharCount ];
-        mpGlyphs2Chars = new int[ mnCharCount ];
-        for( i = 0; i < mnCharCount; ++i )
-            mpChars2Glyphs[i] = mpGlyphs2Chars[i] = -1;
-
-        mnGlyphCount = 0;
-        rArgs.ResetPos();
-        bool bIsRTL = false;
-        while( rArgs.GetNextRun( &i, &j, &bIsRTL ) )
-        {
-            do
-            {
-                // get the next leftmost character in this run
-                int nCharPos = bIsRTL ? --j : i++;
-                sal_UCS4 cChar = rArgs.mpStr[ nCharPos ];
-
-                // in the RTL case mirror the character and remember its RTL status
-                if( bIsRTL )
-                {
-                    cChar = GetMirroredChar( cChar );
-                    mpGlyphRTLFlags[ mnGlyphCount ] = true;
-                }
-
-                // rewrite the original string
-                // update the mappings between original and rewritten string
-               // TODO: support surrogates in rewritten strings
-                pRewrittenStr[ mnGlyphCount ] = static_cast<sal_Unicode>(cChar);
-                mpGlyphs2Chars[ mnGlyphCount ] = nCharPos;
-                mpChars2Glyphs[ nCharPos - rArgs.mnMinCharPos ] = mnGlyphCount;
-                ++mnGlyphCount;
-            } while( i < j );
-        }
-    }
-
-    mpOutGlyphs     = new WCHAR[ mnGlyphCount ];
-    mpGlyphAdvances = new int[ mnGlyphCount ];
-
-    if( rArgs.mnFlags & (SalLayoutFlags::KerningPairs | SalLayoutFlags::KerningAsian) )
-        mpGlyphOrigAdvs = new int[ mnGlyphCount ];
-
-    for( i = 0; i < mnGlyphCount; ++i )
-        mpOutGlyphs[i] = pBidiStr[ i ];
-    mnWidth = 0;
-    for( i = 0; i < mnGlyphCount; ++i )
-    {
-        // get the current UCS-4 code point, check for surrogate pairs
-        const WCHAR* pCodes = reinterpret_cast<LPCWSTR>(&pBidiStr[i]);
-        unsigned nCharCode = pCodes[0];
-        bool bSurrogate = ((nCharCode >= 0xD800) && (nCharCode <= 0xDFFF));
-        if( bSurrogate )
-        {
-            // ignore high surrogates, they were already processed with their low surrogates
-            if( nCharCode >= 0xDC00 )
-                continue;
-            // check the second half of the surrogate pair
-            bSurrogate &= (0xDC00 <= pCodes[1]) && (pCodes[1] <= 0xDFFF);
-            // calculate the UTF-32 code of valid surrogate pairs
-            if( bSurrogate )
-                nCharCode = 0x10000 + ((pCodes[0] - 0xD800) << 10) + (pCodes[1] - 0xDC00);
-            else // or fall back to a replacement character
-                nCharCode = '?';
-        }
-
-        // get the advance width for the current UTF-32 code point
-        int nGlyphWidth = mrWinFontEntry.GetCachedGlyphWidth( nCharCode );
-        if( nGlyphWidth == -1 )
-        {
-            ABC aABC;
-            SIZE aExtent;
-            if( GetTextExtentPoint32W( mhDC, &pCodes[0], bSurrogate ? 2 : 1, &aExtent) )
-                nGlyphWidth = aExtent.cx;
-            else if( GetCharABCWidthsW( mhDC, nCharCode, nCharCode, &aABC ) )
-                nGlyphWidth = aABC.abcA + aABC.abcB + aABC.abcC;
-            else if( !GetCharWidth32W( mhDC, nCharCode, nCharCode, &nGlyphWidth )
-                 &&  !GetCharWidthW( mhDC, nCharCode, nCharCode, &nGlyphWidth ) )
-                    nGlyphWidth = 0;
-            mrWinFontEntry.CacheGlyphWidth( nCharCode, nGlyphWidth );
-        }
-        mpGlyphAdvances[ i ] = nGlyphWidth;
-        mnWidth += nGlyphWidth;
-
-        // the second half of surrogate pair gets a zero width
-        if( bSurrogate && ((i+1) < mnGlyphCount) )
-            mpGlyphAdvances[ i+1 ] = 0;
-
-        // check with the font face if glyph fallback is needed
-        if( mrWinFontData.HasChar( nCharCode ) )
-            continue;
-
-        // request glyph fallback at this position in the string
-        bool bRTL = mpGlyphRTLFlags ? mpGlyphRTLFlags[i] : false;
-        int nCharPos = mpGlyphs2Chars ? mpGlyphs2Chars[i]: i + rArgs.mnMinCharPos;
-        rArgs.NeedFallback( nCharPos, bRTL );
-        if( bSurrogate && ((nCharPos+1) < rArgs.mnLength) )
-            rArgs.NeedFallback( nCharPos+1, bRTL );
-
-        // replace the current glyph shape with the NotDef glyph shape
-        if( rArgs.mnFlags & SalLayoutFlags::ForFallback )
-        {
-            // when we already are layouting for glyph fallback
-            // then a new unresolved glyph is not interesting
-            mnNotdefWidth = 0;
-            mpOutGlyphs[i] = DROPPED_OUTGLYPH;
-        }
-        else
-        {
-            if( mnNotdefWidth < 0 )
-            {
-                // get the width of the NotDef glyph
-                SIZE aExtent;
-                WCHAR cNotDef = rArgs.mpStr[ nCharPos ];
-                mnNotdefWidth = 0;
-                if( GetTextExtentPoint32W( mhDC, &cNotDef, 1, &aExtent) )
-                    mnNotdefWidth = aExtent.cx;
-            }
-        }
-        if( bSurrogate && ((i+1) < mnGlyphCount) )
-            mpOutGlyphs[i+1] = DROPPED_OUTGLYPH;
-
-        // adjust the current glyph width to the NotDef glyph width
-        mnWidth += mnNotdefWidth - mpGlyphAdvances[i];
-        mpGlyphAdvances[i] = mnNotdefWidth;
-        if( mpGlyphOrigAdvs )
-            mpGlyphOrigAdvs[i] = mnNotdefWidth;
-    }
-
-    // apply kerning if the layout engine has not yet done it
-    if( rArgs.mnFlags & (SalLayoutFlags::KerningAsian|SalLayoutFlags::KerningPairs) )
-    {
-        for( i = 0; i < mnGlyphCount; ++i )
-            mpGlyphOrigAdvs[i] = mpGlyphAdvances[i];
-
-        // #99658# also apply asian kerning on the substring border
-        int nLen = mnGlyphCount;
-        if( rArgs.mnMinCharPos + nLen < rArgs.mnLength )
-            ++nLen;
-        for( i = 1; i < nLen; ++i )
-        {
-            if( rArgs.mnFlags & SalLayoutFlags::KerningPairs )
-            {
-                int nKernAmount = mrWinFontEntry.GetKerning( pBidiStr[i-1], pBidiStr[i] );
-                mpGlyphAdvances[ i-1 ] += nKernAmount;
-                mnWidth += nKernAmount;
-            }
-            else if( rArgs.mnFlags & SalLayoutFlags::KerningAsian )
-
-            if( ( (0x3000 == (0xFF00 & pBidiStr[i-1])) || (0x2010 == (0xFFF0 & pBidiStr[i-1])) || (0xFF00 == (0xFF00 & pBidiStr[i-1])))
-            &&  ( (0x3000 == (0xFF00 & pBidiStr[i])) || (0x2010 == (0xFFF0 & pBidiStr[i])) || (0xFF00 == (0xFF00 & pBidiStr[i])) ) )
-            {
-                long nKernFirst = +CalcAsianKerning( pBidiStr[i-1], true, bVertical );
-                long nKernNext  = -CalcAsianKerning( pBidiStr[i], false, bVertical );
-
-                long nDelta = (nKernFirst < nKernNext) ? nKernFirst : nKernNext;
-                if( nDelta<0 && nKernFirst!=0 && nKernNext!=0 )
-                {
-                    nDelta = (nDelta * mpGlyphAdvances[i-1] + 2) / 4;
-                    mpGlyphAdvances[i-1] += nDelta;
-                    mnWidth += nDelta;
-                }
-            }
-        }
-    }
-
-    // calculate virtual char widths
-    if( !mpGlyphs2Chars )
-        mpCharWidths = mpGlyphAdvances;
-    else
-    {
-        mpCharWidths = new int[ mnCharCount ];
-        for( i = 0; i < mnCharCount; ++i )
-            mpCharWidths[ i ] = 0;
-        for( i = 0; i < mnGlyphCount; ++i )
-        {
-            int k = mpGlyphs2Chars[ i ] - rArgs.mnMinCharPos;
-            if( k >= 0 )
-                mpCharWidths[ k ] += mpGlyphAdvances[ i ];
-        }
-    }
-
-    // scale layout metrics if needed
-    // TODO: does it make the code more simple if the metric scaling
-    // is moved to the methods that need metric scaling (e.g. FillDXArray())?
-    if( mfFontScale != 1.0 )
-    {
-        mnWidth   = (long)(mnWidth * mfFontScale);
-        mnBaseAdv = (int)(mnBaseAdv * mfFontScale);
-        for( i = 0; i < mnCharCount; ++i )
-            mpCharWidths[i] = (int)(mpCharWidths[i] * mfFontScale);
-        if( mpGlyphAdvances != mpCharWidths )
-            for( i = 0; i < mnGlyphCount; ++i )
-                mpGlyphAdvances[i] = (int)(mpGlyphAdvances[i] * mfFontScale);
-        if( mpGlyphOrigAdvs && (mpGlyphOrigAdvs != mpGlyphAdvances) )
-            for( i = 0; i < mnGlyphCount; ++i )
-                mpGlyphOrigAdvs[i] = (int)(mpGlyphOrigAdvs[i] * mfFontScale);
-    }
-
-    return true;
-}
-
-int SimpleWinLayout::GetNextGlyphs( int nLen, sal_GlyphId* pGlyphIds, Point& rPos, int& nStart,
-                                    DeviceCoordinate* pGlyphAdvances, int* pCharIndexes,
-                                    const PhysicalFontFace** /*pFallbackFonts*/ ) const
-{
-    // return zero if no more glyph found
-    if( nStart >= mnGlyphCount )
-        return 0;
-
-    // calculate glyph position relative to layout base
-    // TODO: avoid for nStart!=0 case by reusing rPos
-    long nXOffset = mnBaseAdv;
-    for( int i = 0; i < nStart; ++i )
-        nXOffset += mpGlyphAdvances[ i ];
-
-    // calculate absolute position in pixel units
-    Point aRelativePos( nXOffset, 0 );
-    rPos = GetDrawPosition( aRelativePos );
-
-    int nCount = 0;
-    while( nCount < nLen )
-    {
-        // update return values {aGlyphId,nCharPos,nGlyphAdvance}
-        sal_GlyphId aGlyphId = mpOutGlyphs[ nStart ];
-        if( mnLayoutFlags & SalLayoutFlags::Vertical )
-        {
-            const sal_UCS4 cChar = static_cast<sal_UCS4>(aGlyphId & GF_IDXMASK);
-            if( mrWinFontData.HasGSUBstitutions( mhDC )
-            &&  mrWinFontData.IsGSUBstituted( cChar ) )
-                aGlyphId |= GF_GSUB | GF_ROTL;
-            else
-            {
-                aGlyphId |= GetVerticalFlags( cChar );
-                if( (aGlyphId & GF_ROTMASK) == 0 )
-                    aGlyphId |= GF_VERT;
-            }
-        }
-        aGlyphId |= GF_ISCHAR;
-
-        ++nCount;
-        *(pGlyphIds++) = aGlyphId;
-        if( pGlyphAdvances )
-            *(pGlyphAdvances++) = mpGlyphAdvances[ nStart ];
-        if( pCharIndexes )
-        {
-            int nCharPos;
-            if( !mpGlyphs2Chars )
-                nCharPos = nStart + mnMinCharPos;
-            else
-                nCharPos = mpGlyphs2Chars[nStart];
-            *(pCharIndexes++) = nCharPos;
-        }
-
-        // stop at last glyph
-        if( ++nStart >= mnGlyphCount )
-            break;
-
-        // stop when next x-position is unexpected
-        if( !pGlyphAdvances && mpGlyphOrigAdvs )
-            if( mpGlyphAdvances[nStart-1] != mpGlyphOrigAdvs[nStart-1] )
-                break;
-    }
-
-    return nCount;
-}
-
-void SimpleWinLayout::DrawTextImpl(HDC hDC) const
-{
-    if( mnGlyphCount <= 0 )
-        return;
-
-    HFONT hOrigFont = DisableFontScaling();
-    Point aPos = GetDrawPosition( Point( mnBaseAdv, 0 ) );
-
-    // #108267#, break up into glyph portions of a limited size required by Win32 API
-    const unsigned int maxGlyphCount = 8192;
-    UINT numGlyphPortions = mnGlyphCount / maxGlyphCount;
-    UINT remainingGlyphs = mnGlyphCount % maxGlyphCount;
-
-    if( numGlyphPortions )
-    {
-        // #108267#,#109387# break up string into smaller chunks
-        // the output positions will be updated by windows (SetTextAlign)
-        POINT oldPos;
-        UINT oldTa = GetTextAlign(hDC);
-        SetTextAlign(hDC, (oldTa & ~TA_NOUPDATECP) | TA_UPDATECP);
-        MoveToEx(hDC, aPos.X(), aPos.Y(), &oldPos);
-        unsigned int i = 0;
-        for( unsigned int n = 0; n < numGlyphPortions; ++n, i+=maxGlyphCount )
-        {
-            ExtTextOutW(hDC, 0, 0, 0, NULL, mpOutGlyphs+i, maxGlyphCount, mpGlyphAdvances+i);
-        }
-        ExtTextOutW(hDC, 0, 0, 0, NULL, mpOutGlyphs+i, remainingGlyphs, mpGlyphAdvances+i);
-        MoveToEx(hDC, oldPos.x, oldPos.y, (LPPOINT) NULL);
-        SetTextAlign(hDC, oldTa);
-    }
-    else
-        ExtTextOutW(hDC, aPos.X(), aPos.Y(), 0, NULL, mpOutGlyphs, mnGlyphCount, mpGlyphAdvances);
-
-    if( hOrigFont )
-        DeleteFont(SelectFont(hDC, hOrigFont));
-}
-
-DeviceCoordinate SimpleWinLayout::FillDXArray( DeviceCoordinate* pDXArray ) const
-{
-    if( !mnWidth )
-    {
-        mnWidth = mnBaseAdv;
-        for( int i = 0; i < mnGlyphCount; ++i )
-            mnWidth += mpGlyphAdvances[ i ];
-    }
-
-    if( pDXArray != NULL )
-    {
-        for( int i = 0; i < mnCharCount; ++i )
-             pDXArray[ i ] = mpCharWidths[ i ];
-    }
-
-    return mnWidth;
-}
-
-sal_Int32 SimpleWinLayout::GetTextBreak( DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor ) const
-// NOTE: the nFactor is used to prevent rounding errors for small nCharExtra values
-{
-    if( mnWidth )
-        if( (mnWidth * nFactor + mnCharCount * nCharExtra) <= nMaxWidth )
-            return -1;
-
-    long nExtraWidth = mnBaseAdv * nFactor;
-    for( int n = 0; n < mnCharCount; ++n )
-    {
-        // skip unused characters
-        if( mpChars2Glyphs && (mpChars2Glyphs[n] < 0) )
-            continue;
-        // add char widths until max
-        nExtraWidth += mpCharWidths[ n ] * nFactor;
-        if( nExtraWidth > nMaxWidth )
-            return (mnMinCharPos + n);
-        nExtraWidth += nCharExtra;
-    }
-
-    return -1;
-}
-
-void SimpleWinLayout::GetCaretPositions( int nMaxIdx, long* pCaretXArray ) const
-{
-    long nXPos = mnBaseAdv;
-
-    if( !mpGlyphs2Chars )
-    {
-        for( int i = 0; i < nMaxIdx; i += 2 )
-        {
-            pCaretXArray[ i ] = nXPos;
-            nXPos += mpGlyphAdvances[ i>>1 ];
-            pCaretXArray[ i+1 ] = nXPos;
-        }
-    }
-    else
-    {
-        int  i;
-        for( i = 0; i < nMaxIdx; ++i )
-            pCaretXArray[ i ] = -1;
-
-        // assign glyph positions to character positions
-        for( i = 0; i < mnGlyphCount; ++i )
-        {
-            int nCurrIdx = mpGlyphs2Chars[ i ] - mnMinCharPos;
-            long nXRight = nXPos + mpCharWidths[ nCurrIdx ];
-            nCurrIdx *= 2;
-            if( !(mpGlyphRTLFlags && mpGlyphRTLFlags[i]) )
-            {
-                // normal positions for LTR case
-                pCaretXArray[ nCurrIdx ]   = nXPos;
-                pCaretXArray[ nCurrIdx+1 ] = nXRight;
-            }
-            else
-            {
-                // reverse positions for RTL case
-                pCaretXArray[ nCurrIdx ]   = nXRight;
-                pCaretXArray[ nCurrIdx+1 ] = nXPos;
-            }
-            nXPos += mpGlyphAdvances[ i ];
-        }
-    }
-}
-
-void SimpleWinLayout::Justify( DeviceCoordinate nNewWidth )
-{
-    DeviceCoordinate nOldWidth = mnWidth;
-    mnWidth = nNewWidth;
-
-    if( mnGlyphCount <= 0 )
-        return;
-
-    if( nNewWidth == nOldWidth )
-        return;
-
-    // the rightmost glyph cannot be stretched
-    const int nRight = mnGlyphCount - 1;
-    nOldWidth -= mpGlyphAdvances[ nRight ];
-    nNewWidth -= mpGlyphAdvances[ nRight ];
-
-    // count stretchable glyphs
-    int nStretchable = 0, i;
-    for( i = 0; i < nRight; ++i )
-        if( mpGlyphAdvances[i] >= 0 )
-            ++nStretchable;
-
-    // stretch these glyphs
-    DeviceCoordinate nDiffWidth = nNewWidth - nOldWidth;
-    for( i = 0; (i < nRight) && (nStretchable > 0); ++i )
-    {
-        if( mpGlyphAdvances[i] <= 0 )
-            continue;
-        DeviceCoordinate nDeltaWidth = nDiffWidth / nStretchable;
-        mpGlyphAdvances[i] += nDeltaWidth;
-        --nStretchable;
-        nDiffWidth -= nDeltaWidth;
-    }
-}
-
-void SimpleWinLayout::AdjustLayout( ImplLayoutArgs& rArgs )
-{
-    SalLayout::AdjustLayout( rArgs );
-
-    // adjust positions if requested
-    if( rArgs.mpDXArray )
-        ApplyDXArray( rArgs );
-    else if( rArgs.mnLayoutWidth )
-        Justify( rArgs.mnLayoutWidth );
-    else
-        return;
-
-    // recalculate virtual char widths if they were changed
-    if( mpCharWidths != mpGlyphAdvances )
-    {
-        int i;
-        if( !mpGlyphs2Chars )
-        {
-            // standard LTR case
-            for( i = 0; i < mnGlyphCount; ++i )
-                 mpCharWidths[ i ] = mpGlyphAdvances[ i ];
-        }
-        else
-        {
-            // BiDi or complex case
-            for( i = 0; i < mnCharCount; ++i )
-                mpCharWidths[ i ] = 0;
-            for( i = 0; i < mnGlyphCount; ++i )
-            {
-                int j = mpGlyphs2Chars[ i ] - rArgs.mnMinCharPos;
-                if( j >= 0 )
-                    mpCharWidths[ j ] += mpGlyphAdvances[ i ];
-            }
-        }
-    }
-}
-
-void SimpleWinLayout::ApplyDXArray( const ImplLayoutArgs& rArgs )
-{
-    // try to avoid disturbance of text flow for LSB rounding case;
-    const long* pDXArray = rArgs.mpDXArray;
-
-    int i = 0;
-    long nOldWidth = mnBaseAdv;
-    for(; i < mnCharCount; ++i )
-    {
-        int j = !mpChars2Glyphs ? i : mpChars2Glyphs[i];
-        if( j >= 0 )
-        {
-            nOldWidth += mpGlyphAdvances[ j ];
-            long nDiff = nOldWidth - pDXArray[ i ];
-
-            // disabled because of #104768#
-            // works great for static text, but problems when typing
-            // if( nDiff>+1 || nDiff<-1 )
-            // only bother with changing anything when something moved
-            if( nDiff != 0 )
-                break;
-        }
-    }
-    if( i >= mnCharCount )
-        return;
-
-    if( !mpGlyphOrigAdvs )
-    {
-        mpGlyphOrigAdvs = new int[ mnGlyphCount ];
-        for( i = 0; i < mnGlyphCount; ++i )
-            mpGlyphOrigAdvs[ i ] = mpGlyphAdvances[ i ];
-    }
-
-    mnWidth = mnBaseAdv;
-    for( i = 0; i < mnCharCount; ++i )
-    {
-        int j = !mpChars2Glyphs ? i : mpChars2Glyphs[i];
-        if( j >= 0 )
-            mpGlyphAdvances[j] = pDXArray[i] - mnWidth;
-        mnWidth = pDXArray[i];
-    }
-}
-
-void SimpleWinLayout::MoveGlyph( int nStart, long nNewXPos )
-{
-   if( nStart > mnGlyphCount )
-        return;
-
-    // calculate the current x-position of the requested glyph
-    // TODO: cache absolute positions
-    int nXPos = mnBaseAdv;
-    for( int i = 0; i < nStart; ++i )
-        nXPos += mpGlyphAdvances[i];
-
-    // calculate the difference to the current glyph position
-    int nDelta = nNewXPos - nXPos;
-
-    // adjust the width of the layout if it was already cached
-    if( mnWidth )
-        mnWidth += nDelta;
-
-    // depending on whether the requested glyph is leftmost in the layout
-    // adjust either the layout's or the requested glyph's relative position
-    if( nStart > 0 )
-        mpGlyphAdvances[ nStart-1 ] += nDelta;
-    else
-        mnBaseAdv += nDelta;
-}
-
-void SimpleWinLayout::DropGlyph( int nStart )
-{
-    mpOutGlyphs[ nStart ] = DROPPED_OUTGLYPH;
-}
-
-void SimpleWinLayout::Simplify( bool /*bIsBase*/ )
-{
-    // return early if no glyph has been dropped
-    int i = mnGlyphCount;
-    while( (--i >= 0) && (mpOutGlyphs[ i ] != DROPPED_OUTGLYPH) );
-    if( i < 0 )
-        return;
-
-    // convert the layout to a sparse layout if it is not already
-    if( !mpGlyphs2Chars )
-    {
-        mpGlyphs2Chars = new int[ mnGlyphCount ];
-        mpCharWidths = new int[ mnCharCount ];
-        // assertion: mnGlyphCount == mnCharCount
-        for( int k = 0; k < mnGlyphCount; ++k )
-        {
-            mpGlyphs2Chars[ k ] = mnMinCharPos + k;
-            mpCharWidths[ k ] = mpGlyphAdvances[ k ];
-        }
-    }
-
-    // remove dropped glyphs that are rightmost in the layout
-    for( i = mnGlyphCount; --i >= 0; )
-    {
-        if( mpOutGlyphs[ i ] != DROPPED_OUTGLYPH )
-            break;
-        if( mnWidth )
-            mnWidth -= mpGlyphAdvances[ i ];
-        int nRelCharPos = mpGlyphs2Chars[ i ] - mnMinCharPos;
-        if( nRelCharPos >= 0 )
-            mpCharWidths[ nRelCharPos ] = 0;
-    }
-    mnGlyphCount = i + 1;
-
-    // keep original glyph widths around
-    if( !mpGlyphOrigAdvs )
-    {
-        mpGlyphOrigAdvs = new int[ mnGlyphCount ];
-        for( int k = 0; k < mnGlyphCount; ++k )
-            mpGlyphOrigAdvs[ k ] = mpGlyphAdvances[ k ];
-    }
-
-    // remove dropped glyphs inside the layout
-    int nNewGC = 0;
-    for( i = 0; i < mnGlyphCount; ++i )
-    {
-        if( mpOutGlyphs[ i ] == DROPPED_OUTGLYPH )
-        {
-            // adjust relative position to last valid glyph
-            int nDroppedWidth = mpGlyphAdvances[ i ];
-            mpGlyphAdvances[ i ] = 0;
-            if( nNewGC > 0 )
-                mpGlyphAdvances[ nNewGC-1 ] += nDroppedWidth;
-            else
-                mnBaseAdv += nDroppedWidth;
-
-            // zero the virtual char width for the char that has a fallback
-            int nRelCharPos = mpGlyphs2Chars[ i ] - mnMinCharPos;
-            if( nRelCharPos >= 0 )
-                mpCharWidths[ nRelCharPos ] = 0;
-        }
-        else
-        {
-            if( nNewGC != i )
-            {
-                // rearrange the glyph array to get rid of the dropped glyph
-                mpOutGlyphs[ nNewGC ]     = mpOutGlyphs[ i ];
-                mpGlyphAdvances[ nNewGC ] = mpGlyphAdvances[ i ];
-                mpGlyphOrigAdvs[ nNewGC ] = mpGlyphOrigAdvs[ i ];
-                mpGlyphs2Chars[ nNewGC ]  = mpGlyphs2Chars[ i ];
-            }
-            ++nNewGC;
-        }
-    }
-
-    mnGlyphCount = nNewGC;
-    if( mnGlyphCount <= 0 )
-        mnWidth = mnBaseAdv = 0;
-}
-
 struct VisualItem
 {
 public:
@@ -939,7 +251,7 @@ static bool bUspInited = false;
 
 static bool bManualCellAlign = true;
 
-static bool InitUSP()
+static void InitUSP()
 {
     // get the usp10.dll version info
     HMODULE usp10 = GetModuleHandle("usp10.dll");
@@ -973,8 +285,6 @@ static bool InitUSP()
         bManualCellAlign = false;
 
     bUspInited = true;
-
-    return true;
 }
 
 UniscribeLayout::UniscribeLayout(HDC hDC, const ImplWinFontData& rWinFontData,
@@ -2698,40 +2008,21 @@ SalLayout* WinSalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLe
 
     bool bUseOpenGL = OpenGLHelper::isVCLOpenGLEnabled();
 

... etc. - the rest is truncated


More information about the Libreoffice-commits mailing list