diff options
author | Tor Lillqvist <tml@collabora.com> | 2015-08-12 08:18:50 +0300 |
---|---|---|
committer | Tor Lillqvist <tml@collabora.com> | 2015-08-12 09:14:20 +0300 |
commit | 4667db065d34193d99bce82f7e8f3b20a03ecade (patch) | |
tree | 405ac0a286040b8a983701f167c583c45691685b | |
parent | 695cec87d73d56617e1cdc62621971ab35ac67eb (diff) |
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
-rw-r--r-- | vcl/win/source/gdi/winlayout.cxx | 749 | ||||
-rw-r--r-- | vcl/win/source/gdi/winlayout.hxx | 43 |
2 files changed, 20 insertions, 772 deletions
diff --git a/vcl/win/source/gdi/winlayout.cxx b/vcl/win/source/gdi/winlayout.cxx index 9edf88c71e80..ff7f85346b6f 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(); - if( !(rArgs.mnFlags & SalLayoutFlags::ComplexDisabled) - && (bUspInited || InitUSP()) ) // CTL layout engine - { + if (!bUspInited) + InitUSP(); #if ENABLE_GRAPHITE - if (rFontFace.SupportsGraphite()) - { - pWinLayout = new GraphiteWinLayout(getHDC(), rFontFace, rFontInstance, bUseOpenGL); - } - else + 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 - { - 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 ); - } - - BYTE eCharSet = ANSI_CHARSET; -#if ENABLE_GRAPHITE - if (rFontFace.SupportsGraphite()) - pWinLayout = new GraphiteWinLayout(getHDC(), rFontFace, rFontInstance, bUseOpenGL); - else -#endif // ENABLE_GRAPHITE - pWinLayout = new SimpleWinLayout(getHDC(), eCharSet, rFontFace, rFontInstance, bUseOpenGL); - } if( mfFontScale[nFallbackLevel] != 1.0 ) pWinLayout->SetFontScale( mfFontScale[nFallbackLevel] ); @@ -2805,17 +2096,17 @@ bool ImplWinFontEntry::InitKashidaHandling( HDC hDC ) // initialize the kashida width mnMinKashidaWidth = 0; mnMinKashidaGlyph = 0; - if (bUspInited || InitUSP()) - { - SCRIPT_FONTPROPERTIES aFontProperties; - aFontProperties.cBytes = sizeof (aFontProperties); - SCRIPT_CACHE& rScriptCache = GetScriptCache(); - HRESULT nRC = ScriptGetFontProperties( hDC, &rScriptCache, &aFontProperties ); - if( nRC != 0 ) - return false; - mnMinKashidaWidth = aFontProperties.iKashidaWidth; - mnMinKashidaGlyph = aFontProperties.wgKashida; - } + if (!bUspInited) + InitUSP(); + + SCRIPT_FONTPROPERTIES aFontProperties; + aFontProperties.cBytes = sizeof (aFontProperties); + SCRIPT_CACHE& rScriptCache = GetScriptCache(); + HRESULT nRC = ScriptGetFontProperties( hDC, &rScriptCache, &aFontProperties ); + if( nRC != 0 ) + return false; + mnMinKashidaWidth = aFontProperties.iKashidaWidth; + mnMinKashidaGlyph = aFontProperties.wgKashida; return true; } diff --git a/vcl/win/source/gdi/winlayout.hxx b/vcl/win/source/gdi/winlayout.hxx index 7e135ae3504e..7819eae076fa 100644 --- a/vcl/win/source/gdi/winlayout.hxx +++ b/vcl/win/source/gdi/winlayout.hxx @@ -65,49 +65,6 @@ protected: ImplWinFontEntry& mrWinFontEntry; }; -class SimpleWinLayout : public WinLayout -{ -public: - SimpleWinLayout(HDC, BYTE nCharSet, const ImplWinFontData&, ImplWinFontEntry&, bool bUseOpenGL); - virtual ~SimpleWinLayout(); - - virtual bool LayoutText( ImplLayoutArgs& ) SAL_OVERRIDE; - virtual void AdjustLayout( ImplLayoutArgs& ) SAL_OVERRIDE; - virtual void DrawTextImpl(HDC hDC) const SAL_OVERRIDE; - - virtual int GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos, int&, - DeviceCoordinate* pGlyphAdvances, int* pCharIndexes, - const PhysicalFontFace** pFallbackFonts = NULL ) const SAL_OVERRIDE; - - virtual DeviceCoordinate FillDXArray( DeviceCoordinate* pDXArray ) const SAL_OVERRIDE; - virtual sal_Int32 GetTextBreak(DeviceCoordinate nMaxWidth, DeviceCoordinate nCharExtra, int nFactor) const SAL_OVERRIDE; - virtual void GetCaretPositions( int nArraySize, long* pCaretXArray ) const SAL_OVERRIDE; - - // for glyph+font+script fallback - virtual void MoveGlyph( int nStart, long nNewXPos ) SAL_OVERRIDE; - virtual void DropGlyph( int nStart ) SAL_OVERRIDE; - virtual void Simplify( bool bIsBase ) SAL_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: |