LCOV - code coverage report
Current view: top level - libreoffice/vcl/generic/glyphs - gcach_layout.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 184 224 82.1 %
Date: 2012-12-27 Functions: 22 26 84.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /*
       3             :  * This file is part of the LibreOffice project.
       4             :  *
       5             :  * This Source Code Form is subject to the terms of the Mozilla Public
       6             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8             :  *
       9             :  * This file incorporates work covered by the following license notice:
      10             :  *
      11             :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12             :  *   contributor license agreements. See the NOTICE file distributed
      13             :  *   with this work for additional information regarding copyright
      14             :  *   ownership. The ASF licenses this file to you under the Apache
      15             :  *   License, Version 2.0 (the "License"); you may not use this file
      16             :  *   except in compliance with the License. You may obtain a copy of
      17             :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18             :  */
      19             : 
      20             : #include <gcach_ftyp.hxx>
      21             : #include <sallayout.hxx>
      22             : #include <salgdi.hxx>
      23             : 
      24             : #include <vcl/svapp.hxx>
      25             : 
      26             : #include <sal/alloca.h>
      27             : #include <rtl/instance.hxx>
      28             : 
      29             : #include <layout/LayoutEngine.h>
      30             : #include <layout/LEFontInstance.h>
      31             : #include <layout/LEScripts.h>
      32             : 
      33             : #include <unicode/uscript.h>
      34             : #include <unicode/ubidi.h>
      35             : 
      36             : // =======================================================================
      37             : // layout implementation for ServerFont
      38             : // =======================================================================
      39             : 
      40       56398 : ServerFontLayout::ServerFontLayout( ServerFont& rFont )
      41       56398 : :   mrServerFont( rFont )
      42       56398 : {}
      43             : 
      44        7582 : void ServerFontLayout::DrawText( SalGraphics& rSalGraphics ) const
      45             : {
      46        7582 :     rSalGraphics.DrawServerFontLayout( *this );
      47        7582 : }
      48             : 
      49             : // -----------------------------------------------------------------------
      50             : 
      51       56398 : bool ServerFontLayout::LayoutText( ImplLayoutArgs& rArgs )
      52             : {
      53       56398 :     ServerFontLayoutEngine* pLE = mrServerFont.GetLayoutEngine();
      54             :     assert(pLE);
      55       56398 :     bool bRet = pLE ? pLE->layout(*this, rArgs) : false;
      56       56398 :     return bRet;
      57             : }
      58             : 
      59             : // -----------------------------------------------------------------------
      60             : 
      61       58508 : void ServerFontLayout::AdjustLayout( ImplLayoutArgs& rArgs )
      62             : {
      63       58508 :     GenericSalLayout::AdjustLayout( rArgs );
      64             : 
      65             :     // apply asian kerning if the glyphs are not already formatted
      66       58508 :     if( (rArgs.mnFlags & SAL_LAYOUT_KERNING_ASIAN)
      67           0 :     && !(rArgs.mnFlags & SAL_LAYOUT_VERTICAL) )
      68           0 :         if( (rArgs.mpDXArray != NULL) || (rArgs.mnLayoutWidth != 0) )
      69           0 :             ApplyAsianKerning( rArgs.mpStr, rArgs.mnLength );
      70             : 
      71             :     // insert kashidas where requested by the formatting array
      72       58508 :     if( (rArgs.mnFlags & SAL_LAYOUT_KASHIDA_JUSTIFICATON) && rArgs.mpDXArray )
      73             :     {
      74           0 :         int nKashidaIndex = mrServerFont.GetGlyphIndex( 0x0640 );
      75           0 :         if( nKashidaIndex != 0 )
      76             :         {
      77           0 :             const GlyphMetric& rGM = mrServerFont.GetGlyphMetric( nKashidaIndex );
      78           0 :             KashidaJustify( nKashidaIndex, rGM.GetCharWidth() );
      79             :             // TODO: kashida-GSUB/GPOS
      80             :         }
      81             :     }
      82       58508 : }
      83             : 
      84             : // =======================================================================
      85             : // bridge to ICU LayoutEngine
      86             : // =======================================================================
      87             : 
      88             : using namespace U_ICU_NAMESPACE;
      89             : 
      90             : static const LEGlyphID ICU_DELETED_GLYPH = 0xFFFF;
      91             : static const LEGlyphID ICU_MARKED_GLYPH = 0xFFFE;
      92             : 
      93             : // -----------------------------------------------------------------------
      94             : 
      95         872 : class IcuFontFromServerFont
      96             : : public LEFontInstance
      97             : {
      98             : private:
      99             :     ServerFont&     mrServerFont;
     100             : 
     101             : public:
     102         872 :                             IcuFontFromServerFont( ServerFont& rFont )
     103         872 :                             : mrServerFont( rFont )
     104         872 :                             {}
     105             : 
     106             :     virtual const void*     getFontTable(LETag tableTag) const;
     107             :     virtual le_int32        getUnitsPerEM() const;
     108             :     virtual float           getXPixelsPerEm() const;
     109             :     virtual float           getYPixelsPerEm() const;
     110             :     virtual float           getScaleFactorX() const;
     111             :     virtual float           getScaleFactorY() const;
     112             : 
     113             :     using LEFontInstance::mapCharToGlyph;
     114             :     virtual LEGlyphID       mapCharToGlyph( LEUnicode32 ch ) const;
     115             :     virtual LEGlyphID       mapCharToGlyph( LEUnicode32 ch, const LECharMapper *mapper, le_bool filterZeroWidth ) const;
     116             : 
     117             :     virtual le_int32        getAscent() const;
     118             :     virtual le_int32        getDescent() const;
     119             :     virtual le_int32        getLeading() const;
     120             : 
     121             :     virtual void            getGlyphAdvance( LEGlyphID glyph, LEPoint &advance ) const;
     122             :     virtual le_bool         getGlyphPoint( LEGlyphID glyph, le_int32 pointNumber, LEPoint& point ) const;
     123             : };
     124             : 
     125             : // -----------------------------------------------------------------------
     126             : 
     127        3199 : const void* IcuFontFromServerFont::getFontTable( LETag nICUTableTag ) const
     128             : {
     129             :     char pTagName[5];
     130        3199 :     pTagName[0] = (char)(nICUTableTag >> 24);
     131        3199 :     pTagName[1] = (char)(nICUTableTag >> 16);
     132        3199 :     pTagName[2] = (char)(nICUTableTag >>  8);
     133        3199 :     pTagName[3] = (char)(nICUTableTag);
     134        3199 :     pTagName[4] = 0;
     135             : 
     136             :     sal_uLong nLength;
     137        3199 :     const unsigned char* pBuffer = mrServerFont.GetTable( pTagName, &nLength );
     138             :     SAL_INFO("vcl", "IcuGetTable(\"" << pTagName << "\") => " << pBuffer);
     139             :     SAL_INFO(
     140             :         "vcl",
     141             :         "font( h=" << mrServerFont.GetFontSelData().mnHeight << ", \""
     142             :         << mrServerFont.GetFontFileName()->getStr() << "\" )");
     143        3199 :     return pBuffer;
     144             : }
     145             : 
     146             : // -----------------------------------------------------------------------
     147             : 
     148      897140 : le_int32 IcuFontFromServerFont::getUnitsPerEM() const
     149             : {
     150      897140 :     return mrServerFont.GetEmUnits();
     151             : }
     152             : 
     153             : // -----------------------------------------------------------------------
     154             : 
     155      448570 : float IcuFontFromServerFont::getXPixelsPerEm() const
     156             : {
     157      448570 :     const FontSelectPattern& r = mrServerFont.GetFontSelData();
     158      448570 :     float fX = r.mnWidth ? r.mnWidth : r.mnHeight;
     159      448570 :     return fX;
     160             : }
     161             : 
     162             : // -----------------------------------------------------------------------
     163             : 
     164      448570 : float IcuFontFromServerFont::getYPixelsPerEm() const
     165             : {
     166      448570 :     float fY = mrServerFont.GetFontSelData().mnHeight;
     167      448570 :     return fY;
     168             : }
     169             : 
     170             : // -----------------------------------------------------------------------
     171             : 
     172        7189 : float IcuFontFromServerFont::getScaleFactorX() const
     173             : {
     174        7189 :     return 1.0;
     175             : }
     176             : 
     177             : // -----------------------------------------------------------------------
     178             : 
     179        7189 : float IcuFontFromServerFont::getScaleFactorY() const
     180             : {
     181        7189 :     return 1.0;
     182             : }
     183             : 
     184             : // -----------------------------------------------------------------------
     185             : 
     186      329840 : LEGlyphID IcuFontFromServerFont::mapCharToGlyph( LEUnicode32 ch ) const
     187             : {
     188      329840 :     LEGlyphID nGlyphIndex = mrServerFont.GetRawGlyphIndex( ch );
     189      329840 :     return nGlyphIndex;
     190             : }
     191             : 
     192      225346 : LEGlyphID IcuFontFromServerFont::mapCharToGlyph( LEUnicode32 ch, const LECharMapper *mapper, le_bool /*filterZeroWidth*/ ) const
     193             : {
     194             :     /*
     195             :      fdo#31821, icu has...
     196             :       >│93          if (filterZeroWidth && (mappedChar == 0x200C || mappedChar == 0x200D)) {                                            │
     197             :        │94              return canDisplay(mappedChar) ? 0x0001 : 0xFFFF;                                                                 │
     198             :        │95          }
     199             :      so only the Indic layouts allow the joiners to get mapped to glyphs
     200             :     */
     201      225346 :     return LEFontInstance::mapCharToGlyph( ch, mapper, false );
     202             : }
     203             : 
     204             : // -----------------------------------------------------------------------
     205             : 
     206           0 : le_int32 IcuFontFromServerFont::getAscent() const
     207             : {
     208           0 :     const FT_Size_Metrics& rMetrics = mrServerFont.GetMetricsFT();
     209           0 :     le_int32 nAscent = (+rMetrics.ascender + 32) >> 6;
     210           0 :     return nAscent;
     211             : }
     212             : 
     213             : // -----------------------------------------------------------------------
     214             : 
     215           0 : le_int32 IcuFontFromServerFont::getDescent() const
     216             : {
     217           0 :     const FT_Size_Metrics& rMetrics = mrServerFont.GetMetricsFT();
     218           0 :     le_int32 nDescent = (-rMetrics.descender + 32) >> 6;
     219           0 :     return nDescent;
     220             : }
     221             : 
     222             : // -----------------------------------------------------------------------
     223             : 
     224           0 : le_int32 IcuFontFromServerFont::getLeading() const
     225             : {
     226           0 :     const FT_Size_Metrics& rMetrics = mrServerFont.GetMetricsFT();
     227           0 :     le_int32 nLeading = ((rMetrics.height - rMetrics.ascender + rMetrics.descender) + 32) >> 6;
     228           0 :     return nLeading;
     229             : }
     230             : 
     231             : // -----------------------------------------------------------------------
     232             : 
     233      225346 : void IcuFontFromServerFont::getGlyphAdvance( LEGlyphID nGlyphIndex,
     234             :     LEPoint &advance ) const
     235             : {
     236      225346 :     if( (nGlyphIndex == ICU_MARKED_GLYPH)
     237             :     ||  (nGlyphIndex == ICU_DELETED_GLYPH) )
     238             :     {
     239             :         // deleted glyph or mark glyph has not advance
     240           0 :         advance.fX = 0;
     241             :     }
     242             :     else
     243             :     {
     244      225346 :         const GlyphMetric& rGM = mrServerFont.GetGlyphMetric( nGlyphIndex );
     245      225346 :         advance.fX = rGM.GetCharWidth();
     246             :     }
     247             : 
     248      225346 :     advance.fY = 0;
     249      225346 : }
     250             : 
     251             : // -----------------------------------------------------------------------
     252             : 
     253         220 : le_bool IcuFontFromServerFont::getGlyphPoint( LEGlyphID,
     254             :     le_int32 pointNumber, LEPoint& ) const
     255             : {
     256             :     //TODO: replace dummy implementation
     257             :     SAL_INFO("vcl", "getGlyphPoint(" << pointNumber << ")");
     258         220 :     return false;
     259             : }
     260             : 
     261             : // =======================================================================
     262             : 
     263             : class IcuLayoutEngine : public ServerFontLayoutEngine
     264             : {
     265             : private:
     266             :     IcuFontFromServerFont   maIcuFont;
     267             : 
     268             :     le_int32                meScriptCode;
     269             :     le_int32                mnLayoutFlags;
     270             :     LayoutEngine*           mpIcuLE;
     271             : 
     272             : public:
     273             :                             IcuLayoutEngine( ServerFont& );
     274             :     virtual                 ~IcuLayoutEngine();
     275             : 
     276             :     virtual bool            layout( ServerFontLayout&, ImplLayoutArgs& );
     277             : };
     278             : 
     279             : // -----------------------------------------------------------------------
     280             : 
     281         872 : IcuLayoutEngine::IcuLayoutEngine( ServerFont& rServerFont )
     282             : :   maIcuFont( rServerFont ),
     283             :     meScriptCode( USCRIPT_INVALID_CODE ),
     284             :     mnLayoutFlags( 0 ),
     285         872 :     mpIcuLE( NULL )
     286         872 : {}
     287             : 
     288             : // -----------------------------------------------------------------------
     289             : 
     290        2616 : IcuLayoutEngine::~IcuLayoutEngine()
     291             : {
     292         872 :     delete mpIcuLE;
     293        1744 : }
     294             : 
     295             : // -----------------------------------------------------------------------
     296             : 
     297         310 : static bool lcl_CharIsJoiner(sal_Unicode cChar)
     298             : {
     299         310 :     return ((cChar == 0x200C) || (cChar == 0x200D));
     300             : }
     301             : 
     302             : //See https://bugs.freedesktop.org/show_bug.cgi?id=31016
     303             : #define ARABIC_BANDAID
     304             : 
     305       56398 : bool IcuLayoutEngine::layout(ServerFontLayout& rLayout, ImplLayoutArgs& rArgs)
     306             : {
     307       56398 :     le_int32 nLayoutFlags = 0;
     308             : #if (U_ICU_VERSION_MAJOR_NUM > 4)
     309             :     if (rArgs.mnFlags & SAL_LAYOUT_KERNING_PAIRS)
     310             :         nLayoutFlags |= LayoutEngine::kTypoFlagKern;
     311             :     if (rArgs.mnFlags & SAL_LAYOUT_ENABLE_LIGATURES)
     312             :         nLayoutFlags |= LayoutEngine::kTypoFlagLiga;
     313             : #else
     314       56398 :     if (rArgs.mnFlags & SAL_LAYOUT_KERNING_PAIRS)
     315         903 :         nLayoutFlags |= 0x01;
     316       56398 :     if (rArgs.mnFlags & SAL_LAYOUT_ENABLE_LIGATURES)
     317           0 :         nLayoutFlags |= 0x10;
     318             : #endif
     319             : 
     320             :     LEUnicode* pIcuChars;
     321             :     if( sizeof(LEUnicode) == sizeof(*rArgs.mpStr) )
     322       56398 :         pIcuChars = (LEUnicode*)rArgs.mpStr;
     323             :     else
     324             :     {
     325             :         // this conversion will only be needed when either
     326             :         // ICU's or OOo's unicodes stop being unsigned shorts
     327             :         // TODO: watch out for surrogates!
     328             :         pIcuChars = (LEUnicode*)alloca( rArgs.mnLength * sizeof(LEUnicode) );
     329             :         for( xub_StrLen ic = 0; ic < rArgs.mnLength; ++ic )
     330             :             pIcuChars[ic] = static_cast<LEUnicode>( rArgs.mpStr[ic] );
     331             :     }
     332             : 
     333             :     // allocate temporary arrays, note: round to even
     334       56398 :     int nGlyphCapacity = (3 * (rArgs.mnEndCharPos - rArgs.mnMinCharPos ) | 15) + 1;
     335             : 
     336       56398 :     rLayout.Reserve(nGlyphCapacity);
     337             : 
     338             :     struct IcuPosition{ float fX, fY; };
     339       56398 :     const int nAllocSize = sizeof(LEGlyphID) + sizeof(le_int32) + sizeof(IcuPosition);
     340       56398 :     LEGlyphID* pIcuGlyphs = (LEGlyphID*)alloca( (nGlyphCapacity * nAllocSize) + sizeof(IcuPosition) );
     341       56398 :     le_int32* pCharIndices = (le_int32*)((char*)pIcuGlyphs + nGlyphCapacity * sizeof(LEGlyphID) );
     342       56398 :     IcuPosition* pGlyphPositions = (IcuPosition*)((char*)pCharIndices + nGlyphCapacity * sizeof(le_int32) );
     343             : 
     344       56398 :     ServerFont& rFont = rLayout.GetServerFont();
     345             : 
     346       56398 :     UErrorCode rcI18n = U_ZERO_ERROR;
     347       56398 :     LEErrorCode rcIcu = LE_NO_ERROR;
     348       56398 :     Point aNewPos( 0, 0 );
     349      112804 :     for( int nGlyphCount = 0;; )
     350             :     {
     351             :         int nMinRunPos, nEndRunPos;
     352             :         bool bRightToLeft;
     353      112804 :         if( !rArgs.GetNextRun( &nMinRunPos, &nEndRunPos, &bRightToLeft ) )
     354             :             break;
     355             : 
     356             :         // find matching script
     357             :         // TODO: split up bidi run into script runs
     358       56406 :         le_int32 eScriptCode = -1;
     359      280501 :         for( int i = nMinRunPos; i < nEndRunPos; ++i )
     360             :         {
     361      224951 :             le_int32 eNextScriptCode = uscript_getScript( pIcuChars[i], &rcI18n );
     362      224951 :             if( (eNextScriptCode > USCRIPT_INHERITED) )
     363             :             {
     364      136083 :                 eScriptCode = eNextScriptCode;
     365      136083 :                 if (eNextScriptCode != latnScriptCode)
     366         856 :                     break;
     367             :             }
     368             :         }
     369       56406 :         if( eScriptCode < 0 )   // TODO: handle errors better
     370       38236 :             eScriptCode = latnScriptCode;
     371             : 
     372             :         // get layout engine matching to this script and ligature/kerning combination
     373             :         // no engine change necessary if script is latin
     374       56406 :         if( !mpIcuLE || ((eScriptCode != meScriptCode) && (eScriptCode > USCRIPT_INHERITED)) || (mnLayoutFlags != nLayoutFlags) )
     375             :         {
     376             :             // TODO: cache multiple layout engines when multiple scripts are used
     377        1151 :             delete mpIcuLE;
     378        1151 :             meScriptCode = eScriptCode;
     379        1151 :             mnLayoutFlags = nLayoutFlags;
     380        1151 :             le_int32 eLangCode = 0; // TODO: get better value
     381        1151 :             mpIcuLE = LayoutEngine::layoutEngineFactory( &maIcuFont, eScriptCode, eLangCode, nLayoutFlags, rcIcu );
     382        1151 :             if( LE_FAILURE(rcIcu) )
     383             :             {
     384           0 :                 delete mpIcuLE;
     385           0 :                 mpIcuLE = NULL;
     386             :             }
     387             :         }
     388             : 
     389             :         // fall back to default layout if needed
     390       56406 :         if( !mpIcuLE )
     391             :             break;
     392             : 
     393             :         // run ICU layout engine
     394             :         // TODO: get enough context, remove extra glyps below
     395             :         int nRawRunGlyphCount = mpIcuLE->layoutChars( pIcuChars,
     396             :             nMinRunPos, nEndRunPos - nMinRunPos, rArgs.mnLength,
     397       56406 :             bRightToLeft, aNewPos.X(), aNewPos.Y(), rcIcu );
     398       56406 :         if( LE_FAILURE(rcIcu) )
     399           0 :             return false;
     400             : 
     401             :         // import layout info from icu
     402       56406 :         mpIcuLE->getGlyphs( pIcuGlyphs, rcIcu );
     403       56406 :         mpIcuLE->getCharIndices( pCharIndices, rcIcu );
     404       56406 :         mpIcuLE->getGlyphPositions( &pGlyphPositions->fX, rcIcu );
     405       56406 :         mpIcuLE->reset(); // TODO: get rid of this, PROBLEM: crash at exit when removed
     406       56406 :         if( LE_FAILURE(rcIcu) )
     407           0 :             return false;
     408             : 
     409             :         // layout bidi/script runs and export them to a ServerFontLayout
     410             :         // convert results to GlyphItems
     411       56406 :         int nLastCharPos = -1;
     412       56406 :         int nClusterMinPos = -1;
     413       56406 :         int nClusterMaxPos = -1;
     414       56406 :         bool bClusterStart = true;
     415       56406 :         int nFilteredRunGlyphCount = 0;
     416       56406 :         const IcuPosition* pPos = pGlyphPositions;
     417      281752 :         for( int i = 0; i < nRawRunGlyphCount; ++i, ++pPos )
     418             :         {
     419      225346 :             LEGlyphID nGlyphIndex = pIcuGlyphs[i];
     420             :             // ignore glyphs which were marked or deleted by ICU
     421      225346 :             if( (nGlyphIndex == ICU_MARKED_GLYPH)
     422             :             ||  (nGlyphIndex == ICU_DELETED_GLYPH) )
     423           0 :                 continue;
     424             : 
     425             :             // adjust the relative char pos
     426      225346 :             int nCharPos = pCharIndices[i];
     427      225346 :             if( nCharPos >= 0 ) {
     428      225346 :                 nCharPos += nMinRunPos;
     429             :                 // ICU seems to return bad pCharIndices
     430             :                 // for some combinations of ICU+font+text
     431             :                 // => better give up now than crash later
     432      225346 :                 if( nCharPos >= nEndRunPos )
     433           0 :                     continue;
     434             :             }
     435             : 
     436             :             // if needed request glyph fallback by updating LayoutArgs
     437      225346 :             if( !nGlyphIndex )
     438             :             {
     439        3419 :                 if( nCharPos >= 0 )
     440             :                 {
     441        3419 :                     rArgs.NeedFallback( nCharPos, bRightToLeft );
     442        3419 :                     if ( (nCharPos > 0) && lcl_CharIsJoiner(rArgs.mpStr[nCharPos-1]) )
     443           0 :                         rArgs.NeedFallback( nCharPos-1, bRightToLeft );
     444        3419 :                     else if ( (nCharPos + 1 < nEndRunPos) && lcl_CharIsJoiner(rArgs.mpStr[nCharPos+1]) )
     445           0 :                         rArgs.NeedFallback( nCharPos+1, bRightToLeft );
     446             :                 }
     447             : 
     448        3419 :                 if( SAL_LAYOUT_FOR_FALLBACK & rArgs.mnFlags )
     449           0 :                     continue;
     450             :             }
     451             : 
     452             : 
     453             :             // apply vertical flags, etc.
     454      225346 :             bool bDiacritic = false;
     455      225346 :             if( nCharPos >= 0 )
     456             :             {
     457      225346 :                 sal_UCS4 aChar = rArgs.mpStr[ nCharPos ];
     458      225346 :                 nGlyphIndex = rFont.FixupGlyphIndex( nGlyphIndex, aChar );
     459             : 
     460             :                 // #i99367# HACK: try to detect all diacritics
     461      225346 :                 if( aChar>=0x0300 && aChar<0x2100 )
     462        2705 :                     bDiacritic = IsDiacritic( aChar );
     463             :             }
     464             : 
     465             :             // get glyph position and its metrics
     466      225346 :             aNewPos = Point( (int)(pPos->fX+0.5), (int)(pPos->fY+0.5) );
     467      225346 :             const GlyphMetric& rGM = rFont.GetGlyphMetric( nGlyphIndex );
     468      225346 :             int nGlyphWidth = rGM.GetCharWidth();
     469      225346 :             int nNewWidth = nGlyphWidth;
     470      225346 :             if( nGlyphWidth <= 0 )
     471         814 :                 bDiacritic |= true;
     472             :             // #i99367# force all diacritics to zero width
     473             :             // TODO: we need mnOrigWidth/mnLogicWidth/mnNewWidth
     474      224532 :             else if( bDiacritic )
     475         668 :                 nGlyphWidth = nNewWidth = 0;
     476             :             else
     477             :             {
     478             :                 // Hack, find next +ve width glyph and calculate current
     479             :                 // glyph width by substracting the two posituons
     480      223864 :                 const IcuPosition* pNextPos = pPos+1;
     481      223864 :                 for ( int j = i + 1; j <= nRawRunGlyphCount; ++j, ++pNextPos )
     482             :                 {
     483      223864 :                     if ( j == nRawRunGlyphCount )
     484             :                     {
     485       54924 :                         nNewWidth = static_cast<int>(pNextPos->fX - pPos->fX);
     486       54924 :                         break;
     487             :                     }
     488             : 
     489      168940 :                     LEGlyphID nNextGlyphIndex = pIcuGlyphs[j];
     490      168940 :                     if( (nNextGlyphIndex == ICU_MARKED_GLYPH)
     491             :                     ||  (nNextGlyphIndex == ICU_DELETED_GLYPH) )
     492           0 :                         continue;
     493             : 
     494      168940 :                     const GlyphMetric& rNextGM = rFont.GetGlyphMetric( nNextGlyphIndex );
     495      168940 :                     int nNextGlyphWidth = rNextGM.GetCharWidth();
     496      168940 :                     if ( nNextGlyphWidth > 0 )
     497             :                     {
     498      168940 :                         nNewWidth = static_cast<int>(pNextPos->fX - pPos->fX);
     499      168940 :                         break;
     500             :                     }
     501             :                 }
     502             :             }
     503             : 
     504             :             // heuristic to detect glyph clusters
     505      225346 :             bool bInCluster = true;
     506      225346 :             if( nLastCharPos == -1 )
     507             :             {
     508       56406 :                 nClusterMinPos = nClusterMaxPos = nCharPos;
     509       56406 :                 bInCluster = false;
     510             :             }
     511      168940 :             else if( !bRightToLeft )
     512             :             {
     513             :                 // left-to-right case
     514      168825 :                 if( nClusterMinPos > nCharPos )
     515           0 :                     nClusterMinPos = nCharPos;      // extend cluster
     516      168825 :                 else if( nCharPos <= nClusterMaxPos )
     517             :                     /*NOTHING*/;                    // inside cluster
     518      168825 :                 else if( bDiacritic )
     519           0 :                     nClusterMaxPos = nCharPos;      // add diacritic to cluster
     520             :                 else {
     521      168825 :                     nClusterMinPos = nClusterMaxPos = nCharPos; // new cluster
     522      168825 :                     bInCluster = false;
     523             :                 }
     524             :             }
     525             :             else
     526             :             {
     527             :                 // right-to-left case
     528         115 :                 if( nClusterMaxPos < nCharPos )
     529           0 :                     nClusterMaxPos = nCharPos;      // extend cluster
     530         115 :                 else if( nCharPos >= nClusterMinPos )
     531             :                     /*NOTHING*/;                    // inside cluster
     532         115 :                 else if( bDiacritic )
     533             :                 {
     534           0 :                     nClusterMinPos = nCharPos;      // ICU often has [diacritic* baseglyph*]
     535           0 :                     if( bClusterStart ) {
     536           0 :                         nClusterMaxPos = nCharPos;
     537           0 :                         bInCluster = false;
     538             :                     }
     539             :                 }
     540             :                 else
     541             :                 {
     542         115 :                     nClusterMinPos = nClusterMaxPos = nCharPos; // new cluster
     543         115 :                     bInCluster = !bClusterStart;
     544             :                 }
     545             :             }
     546             : 
     547      225346 :             long nGlyphFlags = 0;
     548      225346 :             if( bInCluster )
     549           0 :                 nGlyphFlags |= GlyphItem::IS_IN_CLUSTER;
     550      225346 :             if( bRightToLeft )
     551         137 :                 nGlyphFlags |= GlyphItem::IS_RTL_GLYPH;
     552      225346 :             if( bDiacritic )
     553        1482 :                 nGlyphFlags |= GlyphItem::IS_DIACRITIC;
     554             : 
     555             :             // add resulting glyph item to layout
     556      225346 :             GlyphItem aGI( nCharPos, nGlyphIndex, aNewPos, nGlyphFlags, nGlyphWidth );
     557             : #ifdef ARABIC_BANDAID
     558      225346 :             aGI.mnNewWidth = nNewWidth;
     559             : #endif
     560      225346 :             rLayout.AppendGlyph( aGI );
     561      225346 :             ++nFilteredRunGlyphCount;
     562      225346 :             nLastCharPos = nCharPos;
     563      225346 :             bClusterStart = !aGI.IsDiacritic(); // TODO: only needed in RTL-codepath
     564             :         }
     565       56406 :         aNewPos = Point( (int)(pPos->fX+0.5), (int)(pPos->fY+0.5) );
     566       56406 :         nGlyphCount += nFilteredRunGlyphCount;
     567             :     }
     568             : 
     569             :     // sort glyphs in visual order
     570             :     // and then in logical order (e.g. diacritics after cluster start)
     571       56398 :     rLayout.SortGlyphItems();
     572             : 
     573             :     // determine need for kashida justification
     574       56398 :     if( (rArgs.mpDXArray || rArgs.mnLayoutWidth)
     575             :     &&  ((meScriptCode == arabScriptCode) || (meScriptCode == syrcScriptCode)) )
     576           0 :         rArgs.mnFlags |= SAL_LAYOUT_KASHIDA_JUSTIFICATON;
     577             : 
     578       56398 :     return true;
     579             : }
     580             : 
     581             : // =======================================================================
     582             : 
     583       56398 : ServerFontLayoutEngine* ServerFont::GetLayoutEngine()
     584             : {
     585             :     // find best layout engine for font, platform, script and language
     586       56398 :     if (!mpLayoutEngine)
     587         872 :         mpLayoutEngine = new IcuLayoutEngine(*this);
     588       56398 :     return mpLayoutEngine;
     589             : }
     590             : 
     591             : // =======================================================================
     592             : 
     593             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10