summaryrefslogtreecommitdiffstats
path: root/vcl/os2/source/gdi/os2layout.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'vcl/os2/source/gdi/os2layout.cxx')
-rw-r--r--vcl/os2/source/gdi/os2layout.cxx1041
1 files changed, 0 insertions, 1041 deletions
diff --git a/vcl/os2/source/gdi/os2layout.cxx b/vcl/os2/source/gdi/os2layout.cxx
deleted file mode 100644
index a6574c3a2171..000000000000
--- a/vcl/os2/source/gdi/os2layout.cxx
+++ /dev/null
@@ -1,1041 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*************************************************************************
- *
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * Copyright 2000, 2010 Oracle and/or its affiliates.
- *
- * OpenOffice.org - a multi-platform office productivity suite
- *
- * This file is part of OpenOffice.org.
- *
- * OpenOffice.org is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 3
- * only, as published by the Free Software Foundation.
- *
- * OpenOffice.org is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License version 3 for more details
- * (a copy is included in the LICENSE file that accompanied this code).
- *
- * You should have received a copy of the GNU Lesser General Public License
- * version 3 along with OpenOffice.org. If not, see
- * <http://www.openoffice.org/license.html>
- * for a copy of the LGPLv3 License.
- *
- ************************************************************************/
-
-#include <rtl/ustring.hxx>
-#include <osl/module.h>
-#include <salgdi.h>
-#include <saldata.hxx>
-#include <vcl/sallayout.hxx>
-
-#ifndef __H_FT2LIB
-#include <wingdi.h>
-#include <ft2lib.h>
-#endif
-
-#include <cstdio>
-#include <malloc.h>
-
-#ifdef GCP_KERN_HACK
- #include <algorithm>
-#endif // GCP_KERN_HACK
-
-// for GetMirroredChar
-#include <vcl/svapp.hxx>
-
-#include <boost/unordered_map.hpp>
-typedef boost::unordered_map<int,int> IntMap;
-
-#define DROPPED_OUTGLYPH 0xFFFF
-
-// =======================================================================
-
-// OS/2 specific physical font instance
-class ImplOs2FontEntry : public ImplFontEntry
-{
-public:
- ImplOs2FontEntry( ImplFontSelectData& );
- ~ImplOs2FontEntry();
-
-private:
- // TODO: also add HFONT??? Watch out for issues with too many active fonts...
-
-#ifdef GCP_KERN_HACK
-public:
- bool HasKernData() const;
- void SetKernData( int, const KERNINGPAIRS* );
- int GetKerning( sal_Unicode, sal_Unicode ) const;
-private:
- KERNINGPAIRS* mpKerningPairs;
- int mnKerningPairs;
-#endif // GCP_KERN_HACK
-
-public:
- int GetCachedGlyphWidth( int nCharCode ) const;
- void CacheGlyphWidth( int nCharCode, int nCharWidth );
-private:
- IntMap maWidthMap;
-};
-
-// -----------------------------------------------------------------------
-
-inline void ImplOs2FontEntry::CacheGlyphWidth( int nCharCode, int nCharWidth )
-{
- maWidthMap[ nCharCode ] = nCharWidth;
-}
-
-inline int ImplOs2FontEntry::GetCachedGlyphWidth( int nCharCode ) const
-{
- IntMap::const_iterator it = maWidthMap.find( nCharCode );
- if( it == maWidthMap.end() )
- return -1;
- return it->second;
-}
-
-// =======================================================================
-
-class Os2Layout : public SalLayout
-{
-public:
- Os2Layout( HDC, const ImplOs2FontData&, ImplOs2FontEntry& );
- virtual void InitFont() const;
- void SetFontScale( float f ) { mfFontScale = f; }
- float GetFontScale() const { return mfFontScale; }
-
-protected:
- HPS mhPS; // OS2 device handle
- FATTRS mhFont;
- int mnBaseAdv; // x-offset relative to Layout origin
- float mfFontScale; // allows metrics emulation of huge font sizes
-
- const ImplOs2FontData& mrOs2FontData;
- ImplOs2FontEntry& mrOs2FontEntry;
-};
-
-// =======================================================================
-
-class Os2SalLayout : public Os2Layout
-{
-public:
- Os2SalLayout( HPS, BYTE nCharSet, const ImplOs2FontData&, ImplOs2FontEntry& );
- virtual ~Os2SalLayout();
-
- virtual bool LayoutText( ImplLayoutArgs& );
- virtual void AdjustLayout( ImplLayoutArgs& );
- virtual void DrawText( SalGraphics& ) const;
-
- virtual int GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos, int&,
- sal_Int32* pGlyphAdvances, int* pCharIndexes ) const;
-
- virtual long FillDXArray( long* pDXArray ) const;
- virtual int GetTextBreak( long nMaxWidth, long nCharExtra, int nFactor ) const;
- virtual void GetCaretPositions( int nArraySize, long* pCaretXArray ) const;
-
- // for glyph+font+script fallback
- virtual void MoveGlyph( int nStart, long nNewXPos );
- virtual void DropGlyph( int nStart );
- virtual void Simplify( bool bIsBase );
-
-protected:
- void Justify( long nNewWidth );
- void ApplyDXArray( const ImplLayoutArgs& );
-
-protected:
-
-private:
- int mnGlyphCount;
- int mnCharCount;
- sal_Unicode* 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;
- bool mbDisableGlyphs;
-
- int mnNotdefWidth;
- BYTE mnCharSet;
-
-};
-
-// =======================================================================
-
-Os2Layout::Os2Layout( HPS hPS, const ImplOs2FontData& rWFD, ImplOs2FontEntry& rWFE )
-: mhPS( hPS ),
- mnBaseAdv( 0 ),
- mfFontScale( 1.0 ),
- mrOs2FontData( rWFD ),
- mrOs2FontEntry( rWFE )
-{
- BOOL fSuccess;
- fSuccess = Ft2QueryLogicalFont( mhPS, LCID_BASE, NULL, &mhFont, sizeof(FATTRS));
-}
-
-// -----------------------------------------------------------------------
-
-void Os2Layout::InitFont() const
-{
- // select fallback level 0 font
- APIRET rc = Ft2CreateLogFont( mhPS, NULL, LCID_BASE, (PFATTRS)&mhFont);
-}
-
-// =======================================================================
-
-Os2SalLayout::Os2SalLayout( HPS hPS, BYTE nCharSet,
- const ImplOs2FontData& rOs2FontData, ImplOs2FontEntry& rOs2FontEntry )
-: Os2Layout( hPS, rOs2FontData, rOs2FontEntry ),
- mnGlyphCount( 0 ),
- mnCharCount( 0 ),
- mpOutGlyphs( NULL ),
- mpGlyphAdvances( NULL ),
- mpGlyphOrigAdvs( NULL ),
- mpCharWidths( NULL ),
- mpChars2Glyphs( NULL ),
- mpGlyphs2Chars( NULL ),
- mpGlyphRTLFlags( NULL ),
- mnWidth( 0 ),
- mnNotdefWidth( -1 ),
- mnCharSet( nCharSet ),
- mbDisableGlyphs( false )
-{
- mbDisableGlyphs = true;
-}
-
-// -----------------------------------------------------------------------
-
-Os2SalLayout::~Os2SalLayout()
-{
- delete[] mpGlyphRTLFlags;
- delete[] mpGlyphs2Chars;
- delete[] mpChars2Glyphs;
- if( mpCharWidths != mpGlyphAdvances )
- delete[] mpCharWidths;
- delete[] mpGlyphOrigAdvs;
- delete[] mpGlyphAdvances;
- delete[] mpOutGlyphs;
-}
-
-// -----------------------------------------------------------------------
-
-bool Os2SalLayout::LayoutText( ImplLayoutArgs& rArgs )
-{
- // prepare layout
- // TODO: fix case when recyclying old Os2SalLayout object
- mbDisableGlyphs |= ((rArgs.mnFlags & SAL_LAYOUT_DISABLE_GLYPH_PROCESSING) != 0);
- mnCharCount = rArgs.mnEndCharPos - rArgs.mnMinCharPos;
-
- if( !mbDisableGlyphs )
- {
- // Win32 glyph APIs have serious problems with vertical layout
- // => workaround is to use the unicode methods then
- if( rArgs.mnFlags & SAL_LAYOUT_VERTICAL )
- mbDisableGlyphs = true;
- else
- // use cached value from font face
- mbDisableGlyphs = mrOs2FontData.IsGlyphApiDisabled();
- }
-
- // TODO: use a cached value for bDisableAsianKern from upper layers
-
- // layout text
- int i, j;
-
- mnGlyphCount = 0;
- bool bVertical = (rArgs.mnFlags & SAL_LAYOUT_VERTICAL) != 0;
-
- // 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_Unicode cChar = rArgs.mpStr[ nCharPos ];
-
- // in the RTL case mirror the character and remember its RTL status
- if( bIsRTL )
- {
- cChar = ::GetMirroredChar( cChar );
- mpGlyphRTLFlags[ mnGlyphCount ] = true;
- }
-
- // for vertical writing use vertical alternatives
- if( bVertical )
- {
- sal_Unicode cVert = ::GetVerticalChar( cChar );
- if( cVert )
- cChar = cVert;
- }
-
- // rewrite the original string
- // update the mappings between original and rewritten string
- pRewrittenStr[ mnGlyphCount ] = cChar;
- mpGlyphs2Chars[ mnGlyphCount ] = nCharPos;
- mpChars2Glyphs[ nCharPos - rArgs.mnMinCharPos ] = mnGlyphCount;
- ++mnGlyphCount;
- } while( i < j );
- }
- }
-
- mpOutGlyphs = new sal_Unicode[ mnGlyphCount ];
- mpGlyphAdvances = new int[ mnGlyphCount ];
-
- if( rArgs.mnFlags & (SAL_LAYOUT_KERNING_PAIRS | SAL_LAYOUT_KERNING_ASIAN) )
- mpGlyphOrigAdvs = new int[ mnGlyphCount ];
-
-#ifndef GCP_KERN_HACK
- DWORD nGcpOption = 0;
- // enable kerning if requested
- if( rArgs.mnFlags & SAL_LAYOUT_KERNING_PAIRS )
- nGcpOption |= GCP_USEKERNING;
-#endif // GCP_KERN_HACK
-
- LONG lLcid = Ft2QueryCharSet( mhPS);
-
- for( i = 0; i < mnGlyphCount; ++i )
- mpOutGlyphs[i] = pBidiStr[ i ];
- mnWidth = 0;
- for( i = 0; i < mnGlyphCount; ++i )
- {
- const sal_Unicode* pCodes = &pBidiStr[i];
- // check for surrogate pairs
- if( (pCodes[0] & 0xFC00) == 0xDC00 )
- continue;
- bool bSurrogate = ((pCodes[0] & 0xFC00) == 0xD800);
-
- // get the width of the corresponding code point
- int nCharCode = pCodes[0];
- if( bSurrogate )
- nCharCode = 0x10000 + ((pCodes[0] & 0x03FF) << 10) + (pCodes[1] & 0x03FF);
- int nGlyphWidth = mrOs2FontEntry.GetCachedGlyphWidth( nCharCode );
- if( nGlyphWidth == -1 )
- {
- if (!Ft2QueryStringWidthW( mhPS, (LPWSTR)&pCodes[0], 1, (LONG*)&nGlyphWidth))
- nGlyphWidth = 0;
- mrOs2FontEntry.CacheGlyphWidth( nCharCode, nGlyphWidth );
- }
- mpGlyphAdvances[ i ] = nGlyphWidth;
- mnWidth += nGlyphWidth;
-
- // remaining codes of surrogate pair get a zero width
- if( bSurrogate )
- mpGlyphAdvances[ i+1 ] = 0;
-
- // check with the font face if glyph fallback is needed
- if( mrOs2FontData.HasChar( nCharCode ) )
- continue;
- // Type1 charmaps are not complete (or buggy), use FT2 to check again
- if (Ft2FontSupportsUnicodeChar( mhPS, lLcid, TRUE, nCharCode))
- continue;
-
-#if OSL_DEBUG_LEVEL > 1
- debug_printf("Os2SalLayout::LayoutText font does not support unicode char\n");
-#endif
- // 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 )
- rArgs.NeedFallback( nCharPos+1, bRTL );
-
- if( rArgs.mnFlags & SAL_LAYOUT_FOR_FALLBACK )
- {
- // when we already are layouting for glyph fallback
- // then a new unresolved glyph is not interesting
- mnNotdefWidth = 0;
- mpOutGlyphs[i] = DROPPED_OUTGLYPH;
- if( mbDisableGlyphs && bSurrogate )
- mpOutGlyphs[i+1] = DROPPED_OUTGLYPH;
- }
- else
- {
- if( mnNotdefWidth < 0 )
- {
- // get the width of the NotDef glyph
- LONG aExtent;
- mnNotdefWidth = 0;
- if (Ft2QueryStringWidthW( mhPS, (LPWSTR)&rArgs.mpStr[ nCharPos ], 1, &aExtent))
- mnNotdefWidth = aExtent;
- }
- // use a better NotDef glyph
- if( !mbDisableGlyphs )
- mpOutGlyphs[i] = 0;
- }
-
- // replace the current glyph with the NotDef glyph
- mnWidth += mnNotdefWidth - mpGlyphAdvances[i];
- mpGlyphAdvances[i] = mnNotdefWidth;
- if( mpGlyphOrigAdvs )
- mpGlyphOrigAdvs[i] = mnNotdefWidth;
- }
-
-#ifdef GCP_KERN_HACK
- // apply kerning if the layout engine has not yet done it
- if( rArgs.mnFlags & (SAL_LAYOUT_KERNING_ASIAN|SAL_LAYOUT_KERNING_PAIRS) )
- {
-#else // GCP_KERN_HACK
- // apply just asian kerning
- if( rArgs.mnFlags & SAL_LAYOUT_KERNING_ASIAN )
- {
- if( !(rArgs.mnFlags & SAL_LAYOUT_KERNING_PAIRS) )
-#endif // GCP_KERN_HACK
- 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 )
- {
-#ifdef GCP_KERN_HACK
- if( rArgs.mnFlags & SAL_LAYOUT_KERNING_PAIRS )
- {
- int nKernAmount = mrOs2FontEntry.GetKerning( pBidiStr[i-1], pBidiStr[i] );
- mpGlyphAdvances[ i-1 ] += nKernAmount;
- mnWidth += nKernAmount;
- }
- else if( rArgs.mnFlags & SAL_LAYOUT_KERNING_ASIAN )
-#endif // GCP_KERN_HACK
-
- if( (0x3000 == (0xFF00 & pBidiStr[i-1]))
- && (0x3000 == (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 j = mpGlyphs2Chars[ i ] - rArgs.mnMinCharPos;
- if( j >= 0 )
- mpCharWidths[ j ] += mpGlyphAdvances[ i ];
- }
- }
-
- // scale layout metrics if needed
- if( mfFontScale != 1.0 )
- {
- mnWidth *= mfFontScale;
- mnBaseAdv *= mfFontScale;
- for( i = 0; i < mnCharCount; ++i )
- mpCharWidths[ i ] *= mfFontScale;
- if( mpGlyphAdvances != mpCharWidths )
- for( i = 0; i < mnGlyphCount; ++i )
- mpGlyphAdvances[ i ] *= mfFontScale;
- if( mpGlyphOrigAdvs && (mpGlyphOrigAdvs != mpGlyphAdvances) )
- for( i = 0; i < mnGlyphCount; ++i )
- mpGlyphOrigAdvs[ i ] *= mfFontScale;
- }
-
- return true;
-}
-
-// -----------------------------------------------------------------------
-
-int Os2SalLayout::GetNextGlyphs( int nLen, sal_GlyphId* pGlyphs, Point& rPos, int& nStart,
- sal_Int32* pGlyphAdvances, int* pCharIndexes ) 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 {nGlyphIndex,nCharPos,nGlyphAdvance}
- long nGlyphIndex = mpOutGlyphs[ nStart ];
- if( mbDisableGlyphs )
- {
- if( mnLayoutFlags & SAL_LAYOUT_VERTICAL )
- {
- sal_Unicode cChar = (sal_Unicode)(nGlyphIndex & GF_IDXMASK);
-#ifdef GNG_VERT_HACK
- if( mrOs2FontData.HasGSUBstitutions( mhPS )
- && mrOs2FontData.IsGSUBstituted( cChar ) )
- nGlyphIndex |= GF_ROTL | GF_GSUB;
- else
-#endif // GNG_VERT_HACK
- {
- nGlyphIndex |= GetVerticalFlags( cChar );
- if( !(nGlyphIndex & GF_ROTMASK) )
- nGlyphIndex |= GF_VERT;
- }
- }
- nGlyphIndex |= GF_ISCHAR;
- }
- ++nCount;
- *(pGlyphs++) = nGlyphIndex;
- 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 Os2SalLayout::DrawText( SalGraphics& rGraphics ) const
-{
- if( mnGlyphCount <= 0 )
- return;
-
- Point aPos = GetDrawPosition( Point( mnBaseAdv, 0 ) );
- POINTL aPt;
- APIRET rc;
-
- aPt.x = aPos.X();
- aPt.y = static_cast<Os2SalGraphics&>(rGraphics).mnHeight - aPos.Y();
-
- // ft2lib doesn't work with printer hps, so we fallback to codepage printing
- // until cp1200 support will work.
- if (static_cast<Os2SalGraphics&>(rGraphics).mbPrinter) {
- // convert to codepage
- ByteString str( mpOutGlyphs, gsl_getSystemTextEncoding() );
- // gliph size is not recalculated, so it could be wrong!
- rc = Ft2CharStringPosAtA( static_cast<Os2SalGraphics&>(rGraphics).mhPS,
- &aPt, NULL, CHS_VECTOR, mnGlyphCount, (PSZ)str.GetBuffer(),
- (LONG*)mpGlyphAdvances, 0);
- } else {
- // try unicode rendering to screen
- rc = Ft2CharStringPosAtW( static_cast<Os2SalGraphics&>(rGraphics).mhPS,
- &aPt, NULL, CHS_VECTOR, mnGlyphCount, (LPWSTR)mpOutGlyphs,
- (LONG*)mpGlyphAdvances, 0);
- if (rc == GPI_ERROR) {
- // if *W fails, convert to codepage and use *A (fallback to GPI into ft2)
- ByteString str( mpOutGlyphs, gsl_getSystemTextEncoding() );
-#if OSL_DEBUG_LEVEL > 1
- debug_printf("Os2SalLayout::DrawText HPS %08x PosAtW failed '%s'!\n",static_cast<Os2SalGraphics&>(rGraphics).mhPS,str.GetBuffer());
-#endif
- // gliph size is not recalculated, so it could be wrong!
- rc = Ft2CharStringPosAtA( static_cast<Os2SalGraphics&>(rGraphics).mhPS,
- &aPt, NULL, CHS_VECTOR, mnGlyphCount, (PSZ)str.GetBuffer(),
- (LONG*)mpGlyphAdvances, 0);
- }
- }
-}
-
-// -----------------------------------------------------------------------
-
-long Os2SalLayout::FillDXArray( long* pDXArray ) const
-{
- if( !mnWidth )
- {
- long 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;
-}
-
-// -----------------------------------------------------------------------
-
-int Os2SalLayout::GetTextBreak( long nMaxWidth, long 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 STRING_LEN;
-
- 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 STRING_LEN;
-}
-
-// -----------------------------------------------------------------------
-
-void Os2SalLayout::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 Os2SalLayout::Justify( long nNewWidth )
-{
- long 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
- int nDiffWidth = nNewWidth - nOldWidth;
- for( i = 0; (i < nRight) && (nStretchable > 0); ++i )
- {
- if( mpGlyphAdvances[i] <= 0 )
- continue;
- int nDeltaWidth = nDiffWidth / nStretchable;
- mpGlyphAdvances[i] += nDeltaWidth;
- --nStretchable;
- nDiffWidth -= nDeltaWidth;
- }
-}
-
-// -----------------------------------------------------------------------
-
-void Os2SalLayout::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 Os2SalLayout::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 ];
- int 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 Os2SalLayout::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 Os2SalLayout::DropGlyph( int nStart )
-{
- mpOutGlyphs[ nStart ] = DROPPED_OUTGLYPH;
-}
-
-// -----------------------------------------------------------------------
-
-void Os2SalLayout::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;
-}
-
-// =======================================================================
-
-SalLayout* Os2SalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel )
-{
- Os2SalLayout* pLayout = NULL;
- DBG_ASSERT( mpOs2FontEntry[nFallbackLevel], "WinSalGraphics mpWinFontEntry==NULL");
-
- const ImplOs2FontData& rFontFace = *mpOs2FontData[ nFallbackLevel ];
- ImplOs2FontEntry& rFontInstance = *mpOs2FontEntry[ nFallbackLevel ];
-
- {
-#ifdef GCP_KERN_HACK
- if( (rArgs.mnFlags & SAL_LAYOUT_KERNING_PAIRS) && !rFontInstance.HasKernData() )
- {
- // TODO: directly cache kerning info in the rFontInstance
- // TODO: get rid of kerning methods+data in WinSalGraphics object
- GetKernPairs( 0, NULL );
- rFontInstance.SetKernData( mnFontKernPairCount, mpFontKernPairs );
- }
-#endif // GCP_KERN_HACK
-
- pLayout = new Os2SalLayout( mhPS, 0, rFontFace, rFontInstance );
- }
-
- if( mfFontScale != 1.0 )
- pLayout->SetFontScale( mfFontScale );
-
- return pLayout;
-}
-
-// =======================================================================
-
-ImplOs2FontEntry::ImplOs2FontEntry( ImplFontSelectData& rFSD )
-: ImplFontEntry( rFSD ),
- maWidthMap( 512 )
-#ifdef GCP_KERN_HACK
- ,mpKerningPairs( NULL )
- ,mnKerningPairs( -1 )
-#endif // GCP_KERN_HACK
-{
-}
-
-// -----------------------------------------------------------------------
-
-ImplOs2FontEntry::~ImplOs2FontEntry()
-{
-#ifdef GCP_KERN_HACK
- delete[] mpKerningPairs;
-#endif // GCP_KERN_HACK
-}
-
-// -----------------------------------------------------------------------
-
-#ifdef GCP_KERN_HACK
-bool ImplOs2FontEntry::HasKernData() const
-{
- return (mnKerningPairs >= 0);
-}
-
-// -----------------------------------------------------------------------
-
-void ImplOs2FontEntry::SetKernData( int nPairCount, const KERNINGPAIRS* pPairData )
-{
- mnKerningPairs = nPairCount;
- mpKerningPairs = new KERNINGPAIRS[ mnKerningPairs ];
- ::memcpy( mpKerningPairs, (const void*)pPairData, nPairCount*sizeof(KERNINGPAIRS) );
-}
-
-// -----------------------------------------------------------------------
-
-int ImplOs2FontEntry::GetKerning( sal_Unicode cLeft, sal_Unicode cRight ) const
-{
- int nKernAmount = 0;
- if( mpKerningPairs )
- {
- const KERNINGPAIRS aRefPair = { cLeft, cRight, 0 };
- const KERNINGPAIRS* pFirstPair = mpKerningPairs;
- const KERNINGPAIRS* pEndPair = mpKerningPairs + mnKerningPairs;
- const KERNINGPAIRS* pPair = std::lower_bound( pFirstPair,
- pEndPair, aRefPair, ImplCmpKernData );
- if( (pPair != pEndPair)
- && (pPair->sFirstChar == aRefPair.sFirstChar)
- && (pPair->sSecondChar == aRefPair.sSecondChar) )
- nKernAmount = pPair->lKerningAmount;
- }
-
- return nKernAmount;
-}
-#endif // GCP_KERN_HACK
-
-// =======================================================================
-
-ImplFontData* ImplOs2FontData::Clone() const
-{
- if( mpUnicodeMap )
- mpUnicodeMap->AddReference();
- ImplFontData* pClone = new ImplOs2FontData( *this );
- return pClone;
-}
-
-// -----------------------------------------------------------------------
-
-ImplFontEntry* ImplOs2FontData::CreateFontInstance( ImplFontSelectData& rFSD ) const
-{
- ImplFontEntry* pEntry = new ImplOs2FontEntry( rFSD );
- return pEntry;
-}
-
-// =======================================================================
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */