LCOV - code coverage report
Current view: top level - usr/local/src/libreoffice/vcl/generic/glyphs - gcach_layout.cxx (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 164 204 80.4 %
Date: 2013-07-09 Functions: 18 24 75.0 %
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 <boost/static_assert.hpp>
      25             : 
      26             : #include <i18nlangtag/mslangid.hxx>
      27             : 
      28             : #include <vcl/svapp.hxx>
      29             : 
      30             : #include <sal/alloca.h>
      31             : #include <rtl/instance.hxx>
      32             : 
      33             : #include <hb-icu.h>
      34             : #include <hb-ot.h>
      35             : 
      36             : #include <unicode/uscript.h>
      37             : 
      38             : #include <com/sun/star/lang/XMultiServiceFactory.hpp>
      39             : #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
      40             : #include <comphelper/processfactory.hxx>
      41             : 
      42             : // =======================================================================
      43             : // layout implementation for ServerFont
      44             : // =======================================================================
      45             : 
      46      728181 : ServerFontLayout::ServerFontLayout( ServerFont& rFont )
      47      728181 : :   mrServerFont( rFont )
      48      728181 : { }
      49             : 
      50       91323 : void ServerFontLayout::DrawText( SalGraphics& rSalGraphics ) const
      51             : {
      52       91323 :     rSalGraphics.DrawServerFontLayout( *this );
      53       91323 : }
      54             : 
      55             : // -----------------------------------------------------------------------
      56             : 
      57      728181 : bool ServerFontLayout::LayoutText( ImplLayoutArgs& rArgs )
      58             : {
      59      728181 :     ServerFontLayoutEngine* pLE = mrServerFont.GetLayoutEngine();
      60             :     assert(pLE);
      61      728181 :     bool bRet = pLE ? pLE->layout(*this, rArgs) : false;
      62      728181 :     return bRet;
      63             : }
      64             : 
      65             : // -----------------------------------------------------------------------
      66      729128 : void ServerFontLayout::AdjustLayout( ImplLayoutArgs& rArgs )
      67             : {
      68      729128 :     GenericSalLayout::AdjustLayout( rArgs );
      69             : 
      70             :     // apply asian kerning if the glyphs are not already formatted
      71      729128 :     if( (rArgs.mnFlags & SAL_LAYOUT_KERNING_ASIAN)
      72           0 :     && !(rArgs.mnFlags & SAL_LAYOUT_VERTICAL) )
      73           0 :         if( (rArgs.mpDXArray != NULL) || (rArgs.mnLayoutWidth != 0) )
      74           0 :             ApplyAsianKerning( rArgs.mpStr, rArgs.mnLength );
      75             : 
      76             :     // insert kashidas where requested by the formatting array
      77      729128 :     if( (rArgs.mnFlags & SAL_LAYOUT_KASHIDA_JUSTIFICATON) && rArgs.mpDXArray )
      78             :     {
      79           0 :         int nKashidaIndex = mrServerFont.GetGlyphIndex( 0x0640 );
      80           0 :         if( nKashidaIndex != 0 )
      81             :         {
      82           0 :             const GlyphMetric& rGM = mrServerFont.GetGlyphMetric( nKashidaIndex );
      83           0 :             KashidaJustify( nKashidaIndex, rGM.GetCharWidth() );
      84             :             // TODO: kashida-GSUB/GPOS
      85             :         }
      86             :     }
      87      729128 : }
      88             : 
      89        1800 : void ServerFontLayout::setNeedFallback(ImplLayoutArgs& rArgs, sal_Int32 nCharPos,
      90             :     bool bRightToLeft)
      91             : {
      92        1800 :     if (nCharPos < 0)
      93        1800 :         return;
      94             : 
      95             :     using namespace ::com::sun::star;
      96             : 
      97        1800 :     if (!mxBreak.is())
      98             :     {
      99             :         uno::Reference< lang::XMultiServiceFactory > xFactory =
     100        1792 :             comphelper::getProcessServiceFactory();
     101        5376 :         mxBreak = uno::Reference< i18n::XBreakIterator >(xFactory->createInstance(
     102        5376 :             "com.sun.star.i18n.BreakIterator"), uno::UNO_QUERY);
     103             :     }
     104             : 
     105        1800 :     LanguageTag aLangTag(rArgs.meLanguage);
     106        3600 :     lang::Locale aLocale(aLangTag.getLocale());
     107             : 
     108             :     //if position nCharPos is missing in the font, grab the entire grapheme and
     109             :     //mark all glyphs as missing so the whole thing is rendered with the same
     110             :     //font
     111        3600 :     OUString aRun(rArgs.mpStr);
     112             :     sal_Int32 nDone;
     113             :     sal_Int32 nGraphemeStartPos =
     114        1800 :         mxBreak->previousCharacters(aRun, nCharPos+1, aLocale,
     115        1800 :             i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
     116             :     sal_Int32 nGraphemeEndPos =
     117        1800 :         mxBreak->nextCharacters(aRun, nCharPos, aLocale,
     118        1800 :             i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
     119             : 
     120        3600 :     rArgs.NeedFallback(nGraphemeStartPos, nGraphemeEndPos, bRightToLeft);
     121             : }
     122             : 
     123             : // =======================================================================
     124             : 
     125           0 : std::ostream &operator <<(std::ostream& s, ServerFont* pFont)
     126             : {
     127             : #ifndef SAL_LOG_INFO
     128             :     (void) pFont;
     129             : #else
     130             :     FT_Face aFace = pFont->GetFtFace();
     131             :     const char* pName = FT_Get_Postscript_Name(aFace);
     132             :     if (pName)
     133             :         s << pName;
     134             :     else
     135             :         s << pFont->GetFontFileName();
     136             : #endif
     137           0 :     return s;
     138             : }
     139             : 
     140        6864 : static hb_blob_t *getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData)
     141             : {
     142             :     char pTagName[5];
     143        6864 :     pTagName[0] = (char)(nTableTag >> 24);
     144        6864 :     pTagName[1] = (char)(nTableTag >> 16);
     145        6864 :     pTagName[2] = (char)(nTableTag >>  8);
     146        6864 :     pTagName[3] = (char)(nTableTag);
     147        6864 :     pTagName[4] = 0;
     148             : 
     149        6864 :     ServerFont* pFont = (ServerFont*) pUserData;
     150             : 
     151             :     SAL_INFO("vcl.harfbuzz", "getFontTable(" << pFont << ", " << pTagName << ")");
     152             : 
     153             :     sal_uLong nLength;
     154        6864 :     const unsigned char* pBuffer = pFont->GetTable(pTagName, &nLength);
     155             : 
     156        6864 :     hb_blob_t* pBlob = NULL;
     157        6864 :     if (pBuffer != NULL)
     158        5067 :         pBlob = hb_blob_create((const char*) pBuffer, nLength, HB_MEMORY_MODE_READONLY, (void*) pBuffer, NULL);
     159             : 
     160        6864 :     return pBlob;
     161             : }
     162             : 
     163    12062817 : static hb_bool_t getFontGlyph(hb_font_t* /*font*/, void* pFontData,
     164             :         hb_codepoint_t ch, hb_codepoint_t vs,
     165             :         hb_codepoint_t* nGlyphIndex,
     166             :         void* /*pUserData*/)
     167             : {
     168    12062817 :     ServerFont* pFont = (ServerFont*) pFontData;
     169    12062817 :     *nGlyphIndex = pFont->GetRawGlyphIndex(ch, vs);
     170             : 
     171    12062817 :     return *nGlyphIndex != 0;
     172             : }
     173             : 
     174    12057896 : static hb_position_t getGlyphAdvanceH(hb_font_t* /*font*/, void* pFontData,
     175             :         hb_codepoint_t nGlyphIndex,
     176             :         void* /*pUserData*/)
     177             : {
     178    12057896 :     ServerFont* pFont = (ServerFont*) pFontData;
     179    12057896 :     const GlyphMetric& rGM = pFont->GetGlyphMetric(nGlyphIndex);
     180    12057896 :     return rGM.GetCharWidth() << 6;
     181             : }
     182             : 
     183           0 : static hb_position_t getGlyphAdvanceV(hb_font_t* /*font*/, void* /*pFontData*/,
     184             :         hb_codepoint_t /*nGlyphIndex*/,
     185             :         void* /*pUserData*/)
     186             : {
     187             :     // XXX: vertical metrics
     188           0 :     return 0;
     189             : }
     190             : 
     191    36153860 : static hb_bool_t getGlyphOriginH(hb_font_t* /*font*/, void* /*pFontData*/,
     192             :         hb_codepoint_t /*nGlyphIndex*/,
     193             :         hb_position_t* /*x*/, hb_position_t* /*y*/,
     194             :         void* /*pUserData*/)
     195             : {
     196             :     // the horizontal origin is always (0, 0)
     197    36153860 :     return true;
     198             : }
     199             : 
     200           0 : static hb_bool_t getGlyphOriginV(hb_font_t* /*font*/, void* /*pFontData*/,
     201             :         hb_codepoint_t /*nGlyphIndex*/,
     202             :         hb_position_t* /*x*/, hb_position_t* /*y*/,
     203             :         void* /*pUserData*/)
     204             : {
     205             :     // XXX: vertical origin
     206           0 :     return true;
     207             : }
     208             : 
     209        8166 : static hb_position_t getGlyphKerningH(hb_font_t* /*font*/, void* pFontData,
     210             :         hb_codepoint_t nGlyphIndex1, hb_codepoint_t nGlyphIndex2,
     211             :         void* /*pUserData*/)
     212             : {
     213             :     // This callback is for old style 'kern' table, GPOS kerning is handled by HarfBuzz directly
     214             : 
     215             :     // XXX: there is ServerFont::GetKernPairs() but it does many "smart" things
     216             :     // that I'm not sure about, so I'm using FreeType directly
     217             :     // P.S. if we decided not to use ServerFont::GetKernPairs() then it and all
     218             :     // other implementattions should be removed, don't seem to be used
     219             :     // anywhere.
     220             : 
     221        8166 :     ServerFont* pFont = (ServerFont*) pFontData;
     222        8166 :     FT_Face aFace = pFont->GetFtFace();
     223             : 
     224             :     SAL_INFO("vcl.harfbuzz", "getGlyphKerningH(" << pFont << ", " << nGlyphIndex1 << ", " << nGlyphIndex2 << ")");
     225             : 
     226             :     FT_Error error;
     227             :     FT_Vector kerning;
     228             :     hb_position_t ret;
     229             : 
     230        8166 :     error = FT_Get_Kerning(aFace, nGlyphIndex1, nGlyphIndex2, FT_KERNING_DEFAULT, &kerning);
     231        8166 :     if (error)
     232           0 :         ret = 0;
     233             :     else
     234        8166 :         ret = kerning.x;
     235             : 
     236        8166 :     return ret;
     237             : }
     238             : 
     239           0 : static hb_position_t getGlyphKerningV(hb_font_t* /*font*/, void* /*pFontData*/,
     240             :         hb_codepoint_t /*nGlyphIndex1*/, hb_codepoint_t /*nGlyphIndex2*/,
     241             :         void* /*pUserData*/)
     242             : {
     243             :     // XXX vertical kerning
     244           0 :     return 0;
     245             : }
     246             : 
     247           0 : static hb_bool_t getGlyphExtents(hb_font_t* /*font*/, void* pFontData,
     248             :         hb_codepoint_t nGlyphIndex,
     249             :         hb_glyph_extents_t* pExtents,
     250             :         void* /*pUserData*/)
     251             : {
     252           0 :     ServerFont* pFont = (ServerFont*) pFontData;
     253           0 :     FT_Face aFace = pFont->GetFtFace();
     254             : 
     255             :     SAL_INFO("vcl.harfbuzz", "getGlyphExtents(" << pFont << ", " << nGlyphIndex << ")");
     256             : 
     257             :     FT_Error error;
     258           0 :     error = FT_Load_Glyph(aFace, nGlyphIndex, FT_LOAD_DEFAULT);
     259           0 :     if (!error)
     260             :     {
     261           0 :         pExtents->x_bearing = aFace->glyph->metrics.horiBearingX;
     262           0 :         pExtents->y_bearing = aFace->glyph->metrics.horiBearingY;
     263           0 :         pExtents->width  =  aFace->glyph->metrics.width;
     264           0 :         pExtents->height = -aFace->glyph->metrics.height;
     265             :     }
     266             : 
     267           0 :     return !error;
     268             : }
     269             : 
     270           0 : static hb_bool_t getGlyphContourPoint(hb_font_t* /*font*/, void* pFontData,
     271             :         hb_codepoint_t nGlyphIndex, unsigned int nPointIndex,
     272             :         hb_position_t *x, hb_position_t *y,
     273             :         void* /*pUserData*/)
     274             : {
     275           0 :     bool ret = false;
     276           0 :     ServerFont* pFont = (ServerFont*) pFontData;
     277           0 :     FT_Face aFace = pFont->GetFtFace();
     278             : 
     279             :     SAL_INFO("vcl.harfbuzz", "getGlyphContourPoint(" << pFont << ", " << nGlyphIndex << ", " << nPointIndex << ")");
     280             : 
     281             :     FT_Error error;
     282           0 :     error = FT_Load_Glyph(aFace, nGlyphIndex, FT_LOAD_DEFAULT);
     283           0 :     if (!error)
     284             :     {
     285           0 :         if (aFace->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
     286             :         {
     287           0 :             if (nPointIndex < (unsigned int) aFace->glyph->outline.n_points)
     288             :             {
     289           0 :                 *x = aFace->glyph->outline.points[nPointIndex].x;
     290           0 :                 *y = aFace->glyph->outline.points[nPointIndex].y;
     291           0 :                 ret = true;
     292             :             }
     293             :         }
     294             :     }
     295             : 
     296           0 :     return ret;
     297             : }
     298             : 
     299      728181 : static hb_font_funcs_t* getFontFuncs(void)
     300             : {
     301      728181 :     static hb_font_funcs_t* funcs = hb_font_funcs_create();
     302             : 
     303      728181 :     hb_font_funcs_set_glyph_func                (funcs, getFontGlyph, NULL, NULL);
     304      728181 :     hb_font_funcs_set_glyph_h_advance_func      (funcs, getGlyphAdvanceH, NULL, NULL);
     305      728181 :     hb_font_funcs_set_glyph_v_advance_func      (funcs, getGlyphAdvanceV, NULL, NULL);
     306      728181 :     hb_font_funcs_set_glyph_h_origin_func       (funcs, getGlyphOriginH, NULL, NULL);
     307      728181 :     hb_font_funcs_set_glyph_v_origin_func       (funcs, getGlyphOriginV, NULL, NULL);
     308      728181 :     hb_font_funcs_set_glyph_h_kerning_func      (funcs, getGlyphKerningH, NULL, NULL);
     309      728181 :     hb_font_funcs_set_glyph_v_kerning_func      (funcs, getGlyphKerningV, NULL, NULL);
     310      728181 :     hb_font_funcs_set_glyph_extents_func        (funcs, getGlyphExtents, NULL, NULL);
     311      728181 :     hb_font_funcs_set_glyph_contour_point_func  (funcs, getGlyphContourPoint, NULL, NULL);
     312             : 
     313      728181 :     return funcs;
     314             : }
     315             : 
     316             : class HbLayoutEngine : public ServerFontLayoutEngine
     317             : {
     318             : private:
     319             :     UScriptCode             meScriptCode;
     320             :     hb_face_t*              mpHbFace;
     321             :     int                     fUnitsPerEM;
     322             : 
     323             : public:
     324             :                             HbLayoutEngine(ServerFont&);
     325             :     virtual                 ~HbLayoutEngine();
     326             : 
     327             :     virtual bool            layout(ServerFontLayout&, ImplLayoutArgs&);
     328             : };
     329             : 
     330        1716 : HbLayoutEngine::HbLayoutEngine(ServerFont& rServerFont)
     331             : :   meScriptCode(USCRIPT_INVALID_CODE),
     332             :     mpHbFace(NULL),
     333        1716 :     fUnitsPerEM(0)
     334             : {
     335        1716 :     FT_Face aFtFace = rServerFont.GetFtFace();
     336        1716 :     fUnitsPerEM = rServerFont.GetEmUnits();
     337             : 
     338        1716 :     mpHbFace = hb_face_create_for_tables(getFontTable, &rServerFont, NULL);
     339        1716 :     hb_face_set_index(mpHbFace, aFtFace->face_index);
     340        1716 :     hb_face_set_upem(mpHbFace, fUnitsPerEM);
     341        1716 : }
     342             : 
     343        5148 : HbLayoutEngine::~HbLayoutEngine()
     344             : {
     345        1716 :     hb_face_destroy(mpHbFace);
     346        3432 : }
     347             : 
     348      728181 : bool HbLayoutEngine::layout(ServerFontLayout& rLayout, ImplLayoutArgs& rArgs)
     349             : {
     350      728181 :     ServerFont& rFont = rLayout.GetServerFont();
     351      728181 :     FT_Face aFtFace = rFont.GetFtFace();
     352             : 
     353             :     SAL_INFO("vcl.harfbuzz", "layout(" << this << ",rArgs=" << rArgs << ")");
     354             : 
     355      728181 :     hb_font_t *pHbFont = hb_font_create(mpHbFace);
     356      728181 :     hb_font_set_funcs(pHbFont, getFontFuncs(), &rFont, NULL);
     357             :     hb_font_set_scale(pHbFont,
     358      728181 :             ((uint64_t) aFtFace->size->metrics.x_scale * (uint64_t) fUnitsPerEM) >> 16,
     359     1456362 :             ((uint64_t) aFtFace->size->metrics.y_scale * (uint64_t) fUnitsPerEM) >> 16);
     360      728181 :     hb_font_set_ppem(pHbFont, aFtFace->size->metrics.x_ppem, aFtFace->size->metrics.y_ppem);
     361             : 
     362             :     // allocate temporary arrays, note: round to even
     363      728181 :     int nGlyphCapacity = (3 * (rArgs.mnEndCharPos - rArgs.mnMinCharPos) | 15) + 1;
     364             : 
     365      728181 :     rLayout.Reserve(nGlyphCapacity);
     366             : 
     367      728181 :     Point aCurrPos(0, 0);
     368             :     while (true)
     369             :     {
     370             :         int nMinRunPos, nEndRunPos;
     371             :         bool bRightToLeft;
     372     1456338 :         if (!rArgs.GetNextRun(&nMinRunPos, &nEndRunPos, &bRightToLeft))
     373      728181 :             break;
     374             : 
     375      728157 :         int nRunLen = nEndRunPos - nMinRunPos;
     376             : 
     377             :         // find matching script
     378             :         // TODO: use ICU's UScriptRun API to properly resolves "common" and
     379             :         // "inherited" script codes, probably use it in GetNextRun() and return
     380             :         // the script there
     381      728157 :         UScriptCode eScriptCode = USCRIPT_INVALID_CODE;
     382    12789780 :         for (int i = nMinRunPos; i < nEndRunPos; ++i)
     383             :         {
     384    12062431 :             UErrorCode rcI18n = U_ZERO_ERROR;
     385    12062431 :             UScriptCode eNextScriptCode = uscript_getScript(rArgs.mpStr[i], &rcI18n);
     386    12062431 :             if ((eNextScriptCode > USCRIPT_INHERITED))
     387             :             {
     388     5837682 :                 eScriptCode = eNextScriptCode;
     389     5837682 :                 if (eNextScriptCode != USCRIPT_LATIN)
     390         808 :                     break;
     391             :             }
     392             :         }
     393      728157 :         if (eScriptCode < 0)   // TODO: handle errors better
     394      243609 :             eScriptCode = USCRIPT_LATIN;
     395             : 
     396      728157 :         meScriptCode = eScriptCode;
     397             : 
     398      728157 :         LanguageTag aLangTag(rArgs.meLanguage);
     399     1456314 :         OString sLanguage = OUStringToOString(aLangTag.getLanguage(), RTL_TEXTENCODING_UTF8);
     400             : 
     401      728157 :         hb_buffer_t *pHbBuffer = hb_buffer_create();
     402      728157 :         hb_buffer_set_direction(pHbBuffer, bRightToLeft ? HB_DIRECTION_RTL: HB_DIRECTION_LTR);
     403      728157 :         hb_buffer_set_script(pHbBuffer, hb_icu_script_to_script(eScriptCode));
     404      728157 :         hb_buffer_set_language(pHbBuffer, hb_language_from_string(sLanguage.getStr(), -1));
     405      728157 :         hb_buffer_add_utf16(pHbBuffer, rArgs.mpStr, rArgs.mnLength, nMinRunPos, nRunLen);
     406      728157 :         hb_shape(pHbFont, pHbBuffer, NULL, 0);
     407             : 
     408      728157 :         int nRunGlyphCount = hb_buffer_get_length(pHbBuffer);
     409      728157 :         hb_glyph_info_t *pHbGlyphInfos = hb_buffer_get_glyph_infos(pHbBuffer, NULL);
     410      728157 :         hb_glyph_position_t *pHbPositions = hb_buffer_get_glyph_positions(pHbBuffer, NULL);
     411             : 
     412    12786053 :         for (int i = 0; i < nRunGlyphCount; ++i) {
     413    12057896 :             int32_t nGlyphIndex = pHbGlyphInfos[i].codepoint;
     414    12057896 :             int32_t nCharPos = pHbGlyphInfos[i].cluster;
     415             : 
     416             :             // if needed request glyph fallback by updating LayoutArgs
     417    12057896 :             if (!nGlyphIndex)
     418             :             {
     419        1800 :                 rLayout.setNeedFallback(rArgs, nCharPos, bRightToLeft);
     420        1800 :                 if (SAL_LAYOUT_FOR_FALLBACK & rArgs.mnFlags)
     421         845 :                     continue;
     422             :             }
     423             : 
     424             :             // apply vertical flags and glyph substitution
     425             :             // XXX: Use HB_DIRECTION_TTB above and apply whatever flags magic
     426             :             // FixupGlyphIndex() is doing, minus the GSUB part.
     427    12057051 :             if (nCharPos >= 0)
     428             :             {
     429    12057051 :                 sal_UCS4 aChar = rArgs.mpStr[nCharPos];
     430    12057051 :                 nGlyphIndex = rFont.FixupGlyphIndex(nGlyphIndex, aChar);
     431             :             }
     432             : 
     433    12057051 :             bool bInCluster = false;
     434    12057051 :             if (i > 0 && pHbGlyphInfos[i].cluster == pHbGlyphInfos[i - 1].cluster)
     435          48 :                 bInCluster = true;
     436             : 
     437    12057051 :             long nGlyphFlags = 0;
     438    12057051 :             if (bRightToLeft)
     439         168 :                 nGlyphFlags |= GlyphItem::IS_RTL_GLYPH;
     440             : 
     441    12057051 :             if (bInCluster)
     442          48 :                 nGlyphFlags |= GlyphItem::IS_IN_CLUSTER;
     443             : 
     444    12057051 :             bool bDiacritic = false;
     445    12057051 :             if (hb_ot_layout_has_glyph_classes(mpHbFace))
     446             :             {
     447             :                 // the font has GDEF table
     448    12047137 :                 if (hb_ot_layout_get_glyph_class(mpHbFace, nGlyphIndex) == HB_OT_LAYOUT_GLYPH_CLASS_MARK)
     449           8 :                     bDiacritic = true;
     450             :             }
     451             :             else
     452             :             {
     453             :                 // the font lacks GDEF table
     454             :                 // HACK: if the resolved glyph advance is zero assume it is a
     455             :                 // combining mark.  The whole IS_DIACRITIC concept is a hack to
     456             :                 // fix the other hacks we use to second-guess glyph advances in
     457             :                 // ApplyDXArray and the likes and it needs to die
     458        9914 :                 if (pHbPositions[i].x_advance == 0)
     459           0 :                     bDiacritic = true;
     460             :             }
     461             : 
     462    12057051 :             if (bDiacritic)
     463           8 :                 nGlyphFlags |= GlyphItem::IS_DIACRITIC;
     464             : 
     465    12057051 :             int32_t nXOffset =  pHbPositions[i].x_offset >> 6;
     466    12057051 :             int32_t nYOffset =  pHbPositions[i].y_offset >> 6;
     467    12057051 :             int32_t nXAdvance = pHbPositions[i].x_advance >> 6;
     468    12057051 :             int32_t nYAdvance = pHbPositions[i].y_advance >> 6;
     469             : 
     470    12057051 :             Point aNewPos = Point(aCurrPos.X() + nXOffset, -(aCurrPos.Y() + nYOffset));
     471    12057051 :             const GlyphItem aGI(nCharPos, nGlyphIndex, aNewPos, nGlyphFlags, nXAdvance, nXOffset);
     472    12057051 :             rLayout.AppendGlyph(aGI);
     473             : 
     474    12057051 :             aCurrPos.X() += nXAdvance;
     475    12057051 :             aCurrPos.Y() += nYAdvance;
     476             :         }
     477             : 
     478      728157 :         hb_buffer_destroy(pHbBuffer);
     479      728157 :     }
     480             : 
     481      728181 :     hb_font_destroy(pHbFont);
     482             : 
     483             :     // sort glyphs in visual order
     484             :     // and then in logical order (e.g. diacritics after cluster start)
     485             :     // XXX: why?
     486      728181 :     rLayout.SortGlyphItems();
     487             : 
     488             :     // determine need for kashida justification
     489      728181 :     if((rArgs.mpDXArray || rArgs.mnLayoutWidth)
     490       20947 :     && ((meScriptCode == USCRIPT_ARABIC) || (meScriptCode == USCRIPT_SYRIAC)))
     491           0 :         rArgs.mnFlags |= SAL_LAYOUT_KASHIDA_JUSTIFICATON;
     492             : 
     493     1456338 :     return true;
     494             : }
     495             : 
     496             : // =======================================================================
     497             : 
     498      728181 : ServerFontLayoutEngine* ServerFont::GetLayoutEngine()
     499             : {
     500             :     // find best layout engine for font, platform, script and language
     501      728181 :     if (!mpLayoutEngine) {
     502        1716 :         mpLayoutEngine = new HbLayoutEngine(*this);
     503             :     }
     504      728181 :     return mpLayoutEngine;
     505         465 : }
     506             : 
     507             : // =======================================================================
     508             : 
     509             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10