[Libreoffice-commits] core.git: Branch 'feature/fixes14' - 2 commits - configure.ac download.lst external/openssl Makefile.fetch vcl/inc vcl/win

Tor Lillqvist tml at collabora.com
Thu Jan 7 05:58:50 PST 2016


 Makefile.fetch                              |    1 
 configure.ac                                |    9 
 download.lst                                |    2 
 external/openssl/ExternalProject_openssl.mk |    4 
 vcl/inc/win/salgdi.h                        |   11 
 vcl/win/source/gdi/salgdi.cxx               |    5 
 vcl/win/source/gdi/salgdi3.cxx              |   40 +
 vcl/win/source/gdi/winlayout.cxx            |  828 +++++++++++++++++++++++++++-
 vcl/win/source/gdi/winlayout.hxx            |   45 +
 9 files changed, 934 insertions(+), 11 deletions(-)

New commits:
commit 9123edb25359e5e1c781139ac8b02bd361f7a60f
Author: Tor Lillqvist <tml at collabora.com>
Date:   Thu Jan 7 15:05:58 2016 +0200

    tdf#96420: Re-introduce SimpleWinLayout
    
    Should fix lots of problems.
    
    Change-Id: I25c3e3c5ee82241e8a0b12f291b8c7ee84283ef7

diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index 4ff01fa..dd2452f 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -214,6 +214,9 @@ 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:
@@ -330,6 +333,12 @@ protected:
                            const SalBitmap* pAlphaBitmap) override;
     virtual bool       drawAlphaRect( long nX, long nY, long nWidth, long nHeight, sal_uInt8 nTransparency ) 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
 
@@ -451,7 +460,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
-// kerning pairs is sorted by
+// SalGraphicsData::mpFontKernPairs 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 5f29820..42ab90e 100644
--- a/vcl/win/source/gdi/salgdi.cxx
+++ b/vcl/win/source/gdi/salgdi.cxx
@@ -631,6 +631,9 @@ 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)
@@ -660,6 +663,8 @@ WinSalGraphics::~WinSalGraphics()
 
     // delete cache data
     delete [] (BYTE*)mpStdClipRgnData;
+
+    delete [] mpFontKernPairs;
 }
 
 SalGraphicsImpl* WinSalGraphics::GetImpl() const
diff --git a/vcl/win/source/gdi/salgdi3.cxx b/vcl/win/source/gdi/salgdi3.cxx
index 9412799..4de6530 100644
--- a/vcl/win/source/gdi/salgdi3.cxx
+++ b/vcl/win/source/gdi/salgdi3.cxx
@@ -1559,6 +1559,17 @@ 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
@@ -1645,6 +1656,35 @@ 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 cef4f8a..f334fda 100644
--- a/vcl/win/source/gdi/winlayout.cxx
+++ b/vcl/win/source/gdi/winlayout.cxx
@@ -47,6 +47,8 @@
 
 #include <unordered_map>
 
+typedef std::unordered_map<int,int> IntMap;
+
 // Graphite headers
 #include <config_graphite.h>
 #if ENABLE_GRAPHITE
@@ -97,6 +99,15 @@ 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:
@@ -104,6 +115,9 @@ private:
     std::vector<OpenGLGlyphCacheChunk> maOpenGLGlyphCache;
 
 public:
+    int                     GetCachedGlyphWidth( int nCharCode ) const;
+    void                    CacheGlyphWidth( int nCharCode, int nCharWidth );
+
     bool                    InitKashidaHandling( HDC );
     int                     GetMinKashidaWidth() const { return mnMinKashidaWidth; }
     int                     GetMinKashidaGlyph() const { return mnMinKashidaGlyph; }
@@ -117,6 +131,7 @@ public:
     const OpenGLGlyphCacheChunk&  GetCachedGlyphChunkFor(int nGlyphIndex) const;
 
 private:
+    IntMap                  maWidthMap;
     mutable int             mnMinKashidaWidth;
     mutable int             mnMinKashidaGlyph;
     bool                    mbGLyphySetupCalled;
@@ -192,6 +207,19 @@ inline std::basic_ostream<charT, traits> & operator <<(
     return stream << "}";
 }
 
+inline void ImplWinFontEntry::CacheGlyphWidth( int nCharCode, int nCharWidth )
+{
+    maWidthMap[ nCharCode ] = nCharWidth;
+}
+
+inline int ImplWinFontEntry::GetCachedGlyphWidth( int nCharCode ) const
+{
+    IntMap::const_iterator it = maWidthMap.find( nCharCode );
+    if( it == maWidthMap.end() )
+        return -1;
+    return it->second;
+}
+
 bool ImplWinFontEntry::GlyphIsCached(int nGlyphIndex) const
 {
     if (nGlyphIndex == DROPPED_OUTGLYPH)
@@ -443,6 +471,705 @@ bool ImplWinFontEntry::AddChunkOfGlyphs(int nGlyphIndex, const WinLayout& rLayou
     return true;
 }
 
+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.mrStr.pData->buffer + 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.mrStr[ 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.mrStr.getLength()) )
+            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.mrStr[ 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.mrStr.getLength() )
+            ++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;
+}
+
+bool SimpleWinLayout::DrawTextImpl(HDC hDC,
+                                   const Rectangle* pRectToErase,
+                                   Point* /* pPos */,
+                                   int* /* pGetNextGlypInfo */) const
+{
+    if (pRectToErase)
+    {
+        RECT aRect = { pRectToErase->Left(), pRectToErase->Top(), pRectToErase->Left()+pRectToErase->GetWidth(), pRectToErase->Top()+pRectToErase->GetHeight() };
+        FillRect(hDC, &aRect, static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH)));
+    }
+
+    if( mnGlyphCount <= 0 )
+        return false;
+
+    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));
+
+    return false;
+}
+
+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;
+}
+
 const OpenGLGlyphCacheChunk& ImplWinFontEntry::GetCachedGlyphChunkFor(int nGlyphIndex) const
 {
     auto i = maOpenGLGlyphCache.cbegin();
@@ -656,6 +1383,16 @@ void WinLayout::DrawText(SalGraphics& rGraphics) const
     }
 }
 
+bool SimpleWinLayout::CacheGlyphs(SalGraphics& /*rGraphics*/) const
+{
+    return false;
+}
+
+bool SimpleWinLayout::DrawCachedGlyphs(SalGraphics& /*rGraphics*/) const
+{
+    return false;
+}
+
 struct VisualItem
 {
 public:
@@ -2869,7 +3606,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;
 
@@ -2884,18 +3621,56 @@ SalLayout* WinSalGraphics::GetTextLayout( ImplLayoutArgs& /*rArgs*/, int nFallba
 
     if (!bUspInited)
         InitUSP();
-#if ENABLE_GRAPHITE
-    if (rFontFace.SupportsGraphite())
+
+    if( !(rArgs.mnFlags & SalLayoutFlags::ComplexDisabled) )
     {
-        pWinLayout = new GraphiteWinLayout(getHDC(), rFontFace, rFontInstance, bUseOpenGL);
+#if ENABLE_GRAPHITE
+        if (rFontFace.SupportsGraphite())
+        {
+            pWinLayout = new GraphiteWinLayout(getHDC(), rFontFace, rFontInstance, bUseOpenGL);
+        }
+        else
+#endif // ENABLE_GRAPHITE
+        {
+            // script complexity is determined in upper layers
+            pWinLayout = new UniscribeLayout(getHDC(), rFontFace, rFontInstance, bUseOpenGL);
+            // NOTE: it must be guaranteed that the WinSalGraphics lives longer than
+            // the created UniscribeLayout, otherwise the data passed into the
+            // constructor might become invalid too early
+        }
     }
     else
-#endif // ENABLE_GRAPHITE
     {
-        pWinLayout = new UniscribeLayout(getHDC(), rFontFace, rFontInstance, bUseOpenGL);
-        // NOTE: it must be guaranteed that the WinSalGraphics lives longer than
-        // the created UniscribeLayout, otherwise the data passed into the
-        // constructor might become invalid too early
+#if ENABLE_GRAPHITE
+        if (rFontFace.SupportsGraphite())
+        {
+            pWinLayout = new GraphiteWinLayout(getHDC(), rFontFace, rFontInstance, bUseOpenGL);
+        }
+        else
+#endif // ENABLE_GRAPHITE
+        {
+            static bool bAvoidSimpleWinLayout = (std::getenv("VCL_NO_SIMPLEWINLAYOUT") != NULL);
+
+            if (!bAvoidSimpleWinLayout)
+            {
+                if( (rArgs.mnFlags & SalLayoutFlags::KerningPairs) && !rFontInstance.HasKernData() )
+                {
+                    // TODO: directly cache kerning info in the rFontInstance
+                    // TODO: get rid of kerning methods+data in WinSalGraphics object
+                    GetKernPairs();
+                    rFontInstance.SetKernData( mnFontKernPairCount, mpFontKernPairs );
+                }
+
+                pWinLayout = new SimpleWinLayout(getHDC(), ANSI_CHARSET, rFontFace, rFontInstance, bUseOpenGL);
+            }
+            else
+            {
+                pWinLayout = new UniscribeLayout(getHDC(), rFontFace, rFontInstance, bUseOpenGL);
+                // NOTE: it must be guaranteed that the WinSalGraphics lives longer than
+                // the created UniscribeLayout, otherwise the data passed into the
+                // constructor might become invalid too early
+            }
+        }
     }
 
     if( mfFontScale[nFallbackLevel] != 1.0 )
@@ -2917,6 +3692,9 @@ ImplWinFontEntry::ImplWinFontEntry( FontSelectPattern& rFSD )
 :   ImplFontEntry( rFSD )
 ,    mpGLyphyAtlas( nullptr )
 ,    mpGLyphyFont( nullptr )
+,    mpKerningPairs( NULL )
+,    mnKerningPairs( -1 )
+,    maWidthMap( 512 )
 ,    mnMinKashidaWidth( -1 )
 ,    mnMinKashidaGlyph( -1 )
 {
@@ -2929,6 +3707,38 @@ 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 )
diff --git a/vcl/win/source/gdi/winlayout.hxx b/vcl/win/source/gdi/winlayout.hxx
index ff4e5cc..1d2a776 100644
--- a/vcl/win/source/gdi/winlayout.hxx
+++ b/vcl/win/source/gdi/winlayout.hxx
@@ -68,6 +68,51 @@ public:
     ImplWinFontEntry&   mrWinFontEntry;
 };
 
+class SimpleWinLayout : public WinLayout
+{
+public:
+                    SimpleWinLayout(HDC, BYTE nCharSet, const ImplWinFontData&, ImplWinFontEntry&, bool bUseOpenGL);
+    virtual         ~SimpleWinLayout();
+
+    virtual bool    LayoutText( ImplLayoutArgs& ) override;
+    virtual void    AdjustLayout( ImplLayoutArgs& ) override;
+    virtual bool    DrawTextImpl(HDC hDC, const Rectangle* pRectToErase, Point* pPos, int* pGetNextGlypInfo) const override;
+
+    virtual bool    CacheGlyphs(SalGraphics& rGraphics) const override;
+    virtual bool    DrawCachedGlyphs(SalGraphics& rGraphics) const override;
+    virtual int     GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos, int&,
+                                   DeviceCoordinate* pGlyphAdvances, int* pCharIndexes,
+                                   const PhysicalFontFace** pFallbackFonts = NULL ) const override;
+
+    virtual DeviceCoordinate FillDXArray( DeviceCoordinate* pDXArray ) const override;
+    virtual sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const override;
+    virtual void    GetCaretPositions( int nArraySize, long* pCaretXArray ) const override;
+
+    // for glyph+font+script fallback
+    virtual void    MoveGlyph( int nStart, long nNewXPos ) override;
+    virtual void    DropGlyph( int nStart ) override;
+    virtual void    Simplify( bool bIsBase ) override;
+
+protected:
+    void            Justify( DeviceCoordinate nNewWidth );
+    void            ApplyDXArray( const ImplLayoutArgs& );
+
+private:
+    int             mnGlyphCount;
+    int             mnCharCount;
+    WCHAR*          mpOutGlyphs;
+    int*            mpGlyphAdvances;    // if possible this is shared with mpGlyphAdvances[]
+    int*            mpGlyphOrigAdvs;
+    int*            mpCharWidths;       // map rel char pos to char width
+    int*            mpChars2Glyphs;     // map rel char pos to abs glyph pos
+    int*            mpGlyphs2Chars;     // map abs glyph pos to abs char pos
+    bool*           mpGlyphRTLFlags;    // BiDi status for glyphs: true=>RTL
+    mutable long    mnWidth;
+
+    int             mnNotdefWidth;
+    BYTE            mnCharSet;
+};
+
 class UniscribeLayout : public WinLayout
 {
 public:
commit f4d9bd57743de0c595de7f43491c70f17bbd785c
Author: Tor Lillqvist <tml at collabora.com>
Date:   Thu Dec 10 16:57:36 2015 +0200

    Add --with-prebuilt-openssl
    
    Don't ask.
    
    Oh well, if you want to know: For some people, like me, Cygwin and its
    Perl run into horrible trouble with the fork() emulation when building
    OpenSSL. (But my Cygwin works fine for all else in the build. Go
    figure.)
    
    So I came up with a way to use prebuilt OpenSSL binaries. Not to be
    used for release builds, of course (and the configury checks for
    that), as long as our policy is to build all we can from sources.
    
    Change-Id: Ic303bdf0c620c5122aca3d646fa1f0587221e70f

diff --git a/Makefile.fetch b/Makefile.fetch
index 8b2da4e..1e5c984 100644
--- a/Makefile.fetch
+++ b/Makefile.fetch
@@ -192,6 +192,7 @@ $(WORKDIR)/download: $(BUILDDIR)/config_host.mk $(SRCDIR)/download.lst $(SRCDIR)
 		$(call fetch_Optional,PAGEMAKER,PAGEMAKER_TARBALL) \
 		$(call fetch_Optional,POPPLER,POPPLER_TARBALL) \
 		$(call fetch_Optional,POSTGRESQL,POSTGRESQL_TARBALL) \
+		$(call fetch_Optional,PREBUILT_OPENSSL,PREBUILT_OPENSSL_TARBALL) \
 		$(call fetch_Optional,PYTHON,PYTHON_TARBALL) \
 		$(call fetch_Optional,REDLAND,RAPTOR_TARBALL) \
 		$(call fetch_Optional,REDLAND,RASQAL_TARBALL) \
diff --git a/configure.ac b/configure.ac
index 15b3fd2..09076ae 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1469,6 +1469,11 @@ AC_ARG_ENABLE(openssl,
          use only if you are hacking on it.]),
 ,enable_openssl=yes)
 
+AC_ARG_WITH(prebuilt-openssl,
+    AS_HELP_STRING([--with-prebuilt-openssl],
+        [Don't build OpenSSL but use prebuilt binaries. Only for use on Windows, when you can't build it,
+         thanks to the Cygwin fork() problem when running the Perl disaster in OpenSSL's build system.]))
+
 AC_ARG_ENABLE(library-bin-tar,
     AS_HELP_STRING([--enable-library-bin-tar],
         [Enable the building and reused of tarball of binary build for some 'external' libraries.
@@ -8922,6 +8927,10 @@ if test "$with_system_nss" = "yes"; then
     libo_MINGW_CHECK_DLL([ssl3])
 fi
 
+if test $_os = WINNT -a -z "$ENABLE_RELEASE_BUILD" -a "$with_prebuilt_openssl" = yes; then
+    BUILD_TYPE="$BUILD_TYPE PREBUILT_OPENSSL"
+fi
+
 dnl ===================================================================
 dnl Check for system mozilla headers
 dnl ===================================================================
diff --git a/download.lst b/download.lst
index 26912a5..b3f0cad 100755
--- a/download.lst
+++ b/download.lst
@@ -124,6 +124,8 @@ export PNG_TARBALL := libpng-1.6.19.tar.gz
 export POPPLER_MD5SUM := 35c0660065d023365e9854c13e289d12
 export POPPLER_TARBALL := poppler-0.26.4.tar.gz
 export POSTGRESQL_TARBALL := c0b4799ea9850eae3ead14f0a60e9418-postgresql-9.2.1.tar.bz2
+export PREBUILT_OPENSSL_MD5SUM=b91f5c21ab18e8ad993b94092479c39a
+export PREBUILT_OPENSSL_TARBALL=prebuilt-openssl.tar.bz2
 
 ifeq ($(PYTHON_VERSION_MINOR),3)
 export PYTHON_MD5SUM := 803a75927f8f241ca78633890c798021
diff --git a/external/openssl/ExternalProject_openssl.mk b/external/openssl/ExternalProject_openssl.mk
index ea5f8b2..c22ec7b 100644
--- a/external/openssl/ExternalProject_openssl.mk
+++ b/external/openssl/ExternalProject_openssl.mk
@@ -60,6 +60,8 @@ OPENSSL_PLATFORM := \
 
 ifeq ($(COM),MSC)
 $(call gb_ExternalProject_get_state_target,openssl,build):
+	$(if $(filter PREBUILT_OPENSSL,$(BUILD_TYPE)),\
+		cd $(BUILDDIR) && $(GNUTAR) -x -f $(gb_UnpackedTarget_TARFILE_LOCATION)/$(PREBUILT_OPENSSL_TARBALL),\
 	$(call gb_ExternalProject_run,build,\
 		export CC="$(shell cygpath -w $(filter-out -%,$(CC))) $(filter -%,$(CC))" \
 		&& export PERL="$(shell cygpath -w $(PERL))" \
@@ -68,7 +70,7 @@ $(call gb_ExternalProject_get_state_target,openssl,build):
 		&& cmd /c "ms\do_ms.bat $(PERL) $(OPENSSL_PLATFORM)" \
 		&& unset MAKEFLAGS \
 		&& nmake -f "ms\ntdll.mak" \
-	)
+	))
 
 else
 $(call gb_ExternalProject_get_state_target,openssl,build):


More information about the Libreoffice-commits mailing list