LCOV - code coverage report
Current view: top level - vcl/generic/glyphs - gcach_layout.cxx (source / functions) Hit Total Coverage
Test: commit 10e77ab3ff6f4314137acd6e2702a6e5c1ce1fae Lines: 188 227 82.8 %
Date: 2014-11-03 Functions: 21 27 77.8 %
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             : #include <scrptrun.h>
      24             : 
      25             : #include <boost/static_assert.hpp>
      26             : 
      27             : #include <i18nlangtag/mslangid.hxx>
      28             : 
      29             : #include <vcl/svapp.hxx>
      30             : #include <vcl/unohelp.hxx>
      31             : 
      32             : #include <sal/alloca.h>
      33             : #include <rtl/instance.hxx>
      34             : 
      35             : #include <hb-icu.h>
      36             : #include <hb-ot.h>
      37             : 
      38             : #include <com/sun/star/i18n/CharacterIteratorMode.hpp>
      39             : 
      40             : // layout implementation for ServerFont
      41     2156373 : ServerFontLayout::ServerFontLayout( ServerFont& rFont )
      42     2156373 : :   mrServerFont( rFont )
      43             : {
      44     2156373 : }
      45             : 
      46      341169 : void ServerFontLayout::DrawText( SalGraphics& rSalGraphics ) const
      47             : {
      48      341169 :     rSalGraphics.DrawServerFontLayout( *this );
      49      341169 : }
      50             : 
      51     2156373 : bool ServerFontLayout::LayoutText( ImplLayoutArgs& rArgs )
      52             : {
      53     2156373 :     return mrServerFont.GetLayoutEngine()->layout(*this, rArgs);
      54             : }
      55             : 
      56     2157095 : void ServerFontLayout::AdjustLayout( ImplLayoutArgs& rArgs )
      57             : {
      58     2157095 :     GenericSalLayout::AdjustLayout( rArgs );
      59             : 
      60             :     // apply asian kerning if the glyphs are not already formatted
      61     2157095 :     if( (rArgs.mnFlags & SAL_LAYOUT_KERNING_ASIAN)
      62           0 :     && !(rArgs.mnFlags & SAL_LAYOUT_VERTICAL) )
      63           0 :         if( (rArgs.mpDXArray != NULL) || (rArgs.mnLayoutWidth != 0) )
      64           0 :             ApplyAsianKerning( rArgs.mpStr, rArgs.mnLength );
      65             : 
      66             :     // insert kashidas where requested by the formatting array
      67     2157095 :     if( (rArgs.mnFlags & SAL_LAYOUT_KASHIDA_JUSTIFICATON) && rArgs.mpDXArray )
      68             :     {
      69           0 :         int nKashidaIndex = mrServerFont.GetGlyphIndex( 0x0640 );
      70           0 :         if( nKashidaIndex != 0 )
      71             :         {
      72           0 :             const GlyphMetric& rGM = mrServerFont.GetGlyphMetric( nKashidaIndex );
      73           0 :             KashidaJustify( nKashidaIndex, rGM.GetCharWidth() );
      74             :             // TODO: kashida-GSUB/GPOS
      75             :         }
      76             :     }
      77     2157095 : }
      78             : 
      79        2344 : void ServerFontLayout::setNeedFallback(ImplLayoutArgs& rArgs, sal_Int32 nCharPos,
      80             :     bool bRightToLeft)
      81             : {
      82        2344 :     if (nCharPos < 0)
      83        2344 :         return;
      84             : 
      85             :     using namespace ::com::sun::star;
      86             : 
      87        2344 :     if (!mxBreak.is())
      88        2024 :         mxBreak = vcl::unohelper::CreateBreakIterator();
      89             : 
      90        2344 :     lang::Locale aLocale(rArgs.maLanguageTag.getLocale());
      91             : 
      92             :     //if position nCharPos is missing in the font, grab the entire grapheme and
      93             :     //mark all glyphs as missing so the whole thing is rendered with the same
      94             :     //font
      95        4688 :     OUString aRun(rArgs.mpStr);
      96             :     sal_Int32 nDone;
      97             :     sal_Int32 nGraphemeStartPos =
      98        2344 :         mxBreak->previousCharacters(aRun, nCharPos+1, aLocale,
      99        2344 :             i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
     100             :     sal_Int32 nGraphemeEndPos =
     101        2344 :         mxBreak->nextCharacters(aRun, nCharPos, aLocale,
     102        2344 :             i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
     103             : 
     104        4688 :     rArgs.NeedFallback(nGraphemeStartPos, nGraphemeEndPos, bRightToLeft);
     105             : }
     106             : 
     107           0 : std::ostream &operator <<(std::ostream& s, ServerFont* pFont)
     108             : {
     109             : #ifndef SAL_LOG_INFO
     110             :     (void) pFont;
     111             : #else
     112             :     FT_Face aFace = pFont->GetFtFace();
     113             :     const char* pName = FT_Get_Postscript_Name(aFace);
     114             :     if (pName)
     115             :         s << pName;
     116             :     else
     117             :         s << pFont->GetFontFileName();
     118             : #endif
     119           0 :     return s;
     120             : }
     121             : 
     122       29926 : static hb_blob_t *getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData)
     123             : {
     124             :     char pTagName[5];
     125       29926 :     pTagName[0] = (char)(nTableTag >> 24);
     126       29926 :     pTagName[1] = (char)(nTableTag >> 16);
     127       29926 :     pTagName[2] = (char)(nTableTag >>  8);
     128       29926 :     pTagName[3] = (char)(nTableTag);
     129       29926 :     pTagName[4] = 0;
     130             : 
     131       29926 :     ServerFont* pFont = (ServerFont*) pUserData;
     132             : 
     133             :     SAL_INFO("vcl.harfbuzz", "getFontTable(" << pFont << ", " << pTagName << ")");
     134             : 
     135             :     sal_uLong nLength;
     136       29926 :     const unsigned char* pBuffer = pFont->GetTable(pTagName, &nLength);
     137             : 
     138       29926 :     hb_blob_t* pBlob = NULL;
     139       29926 :     if (pBuffer != NULL)
     140       21611 :         pBlob = hb_blob_create((const char*) pBuffer, nLength, HB_MEMORY_MODE_READONLY, (void*) pBuffer, NULL);
     141             : 
     142       29926 :     return pBlob;
     143             : }
     144             : 
     145    41571049 : static hb_bool_t getFontGlyph(hb_font_t* /*font*/, void* pFontData,
     146             :         hb_codepoint_t ch, hb_codepoint_t vs,
     147             :         hb_codepoint_t* nGlyphIndex,
     148             :         void* /*pUserData*/)
     149             : {
     150    41571049 :     ServerFont* pFont = (ServerFont*) pFontData;
     151    41571049 :     *nGlyphIndex = pFont->GetRawGlyphIndex(ch, vs);
     152             : 
     153    41571049 :     return *nGlyphIndex != 0;
     154             : }
     155             : 
     156    41530230 : static hb_position_t getGlyphAdvanceH(hb_font_t* /*font*/, void* pFontData,
     157             :         hb_codepoint_t nGlyphIndex,
     158             :         void* /*pUserData*/)
     159             : {
     160    41530230 :     ServerFont* pFont = (ServerFont*) pFontData;
     161    41530230 :     const GlyphMetric& rGM = pFont->GetGlyphMetric(nGlyphIndex);
     162    41530230 :     return rGM.GetCharWidth() << 6;
     163             : }
     164             : 
     165           0 : static hb_position_t getGlyphAdvanceV(hb_font_t* /*font*/, void* /*pFontData*/,
     166             :         hb_codepoint_t /*nGlyphIndex*/,
     167             :         void* /*pUserData*/)
     168             : {
     169             :     // XXX: vertical metrics
     170           0 :     return 0;
     171             : }
     172             : 
     173   124468374 : static hb_bool_t getGlyphOriginH(hb_font_t* /*font*/, void* /*pFontData*/,
     174             :         hb_codepoint_t /*nGlyphIndex*/,
     175             :         hb_position_t* /*x*/, hb_position_t* /*y*/,
     176             :         void* /*pUserData*/)
     177             : {
     178             :     // the horizontal origin is always (0, 0)
     179   124468374 :     return true;
     180             : }
     181             : 
     182           0 : static hb_bool_t getGlyphOriginV(hb_font_t* /*font*/, void* /*pFontData*/,
     183             :         hb_codepoint_t /*nGlyphIndex*/,
     184             :         hb_position_t* /*x*/, hb_position_t* /*y*/,
     185             :         void* /*pUserData*/)
     186             : {
     187             :     // XXX: vertical origin
     188           0 :     return true;
     189             : }
     190             : 
     191       54282 : static hb_position_t getGlyphKerningH(hb_font_t* /*font*/, void* pFontData,
     192             :         hb_codepoint_t nGlyphIndex1, hb_codepoint_t nGlyphIndex2,
     193             :         void* /*pUserData*/)
     194             : {
     195             :     // This callback is for old style 'kern' table, GPOS kerning is handled by HarfBuzz directly
     196             : 
     197       54282 :     ServerFont* pFont = (ServerFont*) pFontData;
     198       54282 :     FT_Face aFace = pFont->GetFtFace();
     199             : 
     200             :     SAL_INFO("vcl.harfbuzz", "getGlyphKerningH(" << pFont << ", " << nGlyphIndex1 << ", " << nGlyphIndex2 << ")");
     201             : 
     202             :     FT_Error error;
     203             :     FT_Vector kerning;
     204             :     hb_position_t ret;
     205             : 
     206       54282 :     error = FT_Get_Kerning(aFace, nGlyphIndex1, nGlyphIndex2, FT_KERNING_DEFAULT, &kerning);
     207       54282 :     if (error)
     208           0 :         ret = 0;
     209             :     else
     210       54282 :         ret = kerning.x;
     211             : 
     212       54282 :     return ret;
     213             : }
     214             : 
     215           0 : static hb_position_t getGlyphKerningV(hb_font_t* /*font*/, void* /*pFontData*/,
     216             :         hb_codepoint_t /*nGlyphIndex1*/, hb_codepoint_t /*nGlyphIndex2*/,
     217             :         void* /*pUserData*/)
     218             : {
     219             :     // XXX vertical kerning
     220           0 :     return 0;
     221             : }
     222             : 
     223           0 : static hb_bool_t getGlyphExtents(hb_font_t* /*font*/, void* pFontData,
     224             :         hb_codepoint_t nGlyphIndex,
     225             :         hb_glyph_extents_t* pExtents,
     226             :         void* /*pUserData*/)
     227             : {
     228           0 :     ServerFont* pFont = (ServerFont*) pFontData;
     229           0 :     FT_Face aFace = pFont->GetFtFace();
     230             : 
     231             :     SAL_INFO("vcl.harfbuzz", "getGlyphExtents(" << pFont << ", " << nGlyphIndex << ")");
     232             : 
     233             :     FT_Error error;
     234           0 :     error = FT_Load_Glyph(aFace, nGlyphIndex, FT_LOAD_DEFAULT);
     235           0 :     if (!error)
     236             :     {
     237           0 :         pExtents->x_bearing = aFace->glyph->metrics.horiBearingX;
     238           0 :         pExtents->y_bearing = aFace->glyph->metrics.horiBearingY;
     239           0 :         pExtents->width  =  aFace->glyph->metrics.width;
     240           0 :         pExtents->height = -aFace->glyph->metrics.height;
     241             :     }
     242             : 
     243           0 :     return !error;
     244             : }
     245             : 
     246           0 : static hb_bool_t getGlyphContourPoint(hb_font_t* /*font*/, void* pFontData,
     247             :         hb_codepoint_t nGlyphIndex, unsigned int nPointIndex,
     248             :         hb_position_t *x, hb_position_t *y,
     249             :         void* /*pUserData*/)
     250             : {
     251           0 :     bool ret = false;
     252           0 :     ServerFont* pFont = (ServerFont*) pFontData;
     253           0 :     FT_Face aFace = pFont->GetFtFace();
     254             : 
     255             :     SAL_INFO("vcl.harfbuzz", "getGlyphContourPoint(" << pFont << ", " << nGlyphIndex << ", " << nPointIndex << ")");
     256             : 
     257             :     FT_Error error;
     258           0 :     error = FT_Load_Glyph(aFace, nGlyphIndex, FT_LOAD_DEFAULT);
     259           0 :     if (!error)
     260             :     {
     261           0 :         if (aFace->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
     262             :         {
     263           0 :             if (nPointIndex < (unsigned int) aFace->glyph->outline.n_points)
     264             :             {
     265           0 :                 *x = aFace->glyph->outline.points[nPointIndex].x;
     266           0 :                 *y = aFace->glyph->outline.points[nPointIndex].y;
     267           0 :                 ret = true;
     268             :             }
     269             :         }
     270             :     }
     271             : 
     272           0 :     return ret;
     273             : }
     274             : 
     275         290 : static hb_font_funcs_t* getFontFuncs(void)
     276             : {
     277         290 :     static hb_font_funcs_t* funcs = hb_font_funcs_create();
     278             : 
     279         290 :     hb_font_funcs_set_glyph_func                (funcs, getFontGlyph, NULL, NULL);
     280         290 :     hb_font_funcs_set_glyph_h_advance_func      (funcs, getGlyphAdvanceH, NULL, NULL);
     281         290 :     hb_font_funcs_set_glyph_v_advance_func      (funcs, getGlyphAdvanceV, NULL, NULL);
     282         290 :     hb_font_funcs_set_glyph_h_origin_func       (funcs, getGlyphOriginH, NULL, NULL);
     283         290 :     hb_font_funcs_set_glyph_v_origin_func       (funcs, getGlyphOriginV, NULL, NULL);
     284         290 :     hb_font_funcs_set_glyph_h_kerning_func      (funcs, getGlyphKerningH, NULL, NULL);
     285         290 :     hb_font_funcs_set_glyph_v_kerning_func      (funcs, getGlyphKerningV, NULL, NULL);
     286         290 :     hb_font_funcs_set_glyph_extents_func        (funcs, getGlyphExtents, NULL, NULL);
     287         290 :     hb_font_funcs_set_glyph_contour_point_func  (funcs, getGlyphContourPoint, NULL, NULL);
     288             : 
     289         290 :     return funcs;
     290             : }
     291             : 
     292             : // Disabled Unicode compatibility decomposition, see fdo#66715
     293        2344 : static unsigned int unicodeDecomposeCompatibility(hb_unicode_funcs_t* /*ufuncs*/,
     294             :                                                   hb_codepoint_t      /*u*/,
     295             :                                                   hb_codepoint_t*     /*decomposed*/,
     296             :                                                   void*               /*user_data*/)
     297             : {
     298        2344 :     return 0;
     299             : }
     300             : 
     301         290 : static hb_unicode_funcs_t* getUnicodeFuncs(void)
     302             : {
     303         290 :     static hb_unicode_funcs_t* ufuncs = hb_unicode_funcs_create(hb_icu_get_unicode_funcs());
     304         290 :     hb_unicode_funcs_set_decompose_compatibility_func(ufuncs, unicodeDecomposeCompatibility, NULL, NULL);
     305         290 :     return ufuncs;
     306             : }
     307             : 
     308             : class HbLayoutEngine : public ServerFontLayoutEngine
     309             : {
     310             : private:
     311             :     hb_script_t             maHbScript;
     312             :     hb_face_t*              mpHbFace;
     313             :     int                     mnUnitsPerEM;
     314             : 
     315             : public:
     316             :                             HbLayoutEngine(ServerFont&);
     317             :     virtual                 ~HbLayoutEngine();
     318             : 
     319             :     virtual bool            layout(ServerFontLayout&, ImplLayoutArgs&) SAL_OVERRIDE;
     320             : };
     321             : 
     322        7482 : HbLayoutEngine::HbLayoutEngine(ServerFont& rServerFont)
     323             : :   maHbScript(HB_SCRIPT_INVALID),
     324             :     mpHbFace(NULL),
     325        7482 :     mnUnitsPerEM(0)
     326             : {
     327        7482 :     FT_Face aFtFace = rServerFont.GetFtFace();
     328        7482 :     mnUnitsPerEM = rServerFont.GetEmUnits();
     329             : 
     330        7482 :     mpHbFace = hb_face_create_for_tables(getFontTable, &rServerFont, NULL);
     331        7482 :     hb_face_set_index(mpHbFace, aFtFace->face_index);
     332        7482 :     hb_face_set_upem(mpHbFace, mnUnitsPerEM);
     333        7482 : }
     334             : 
     335       22446 : HbLayoutEngine::~HbLayoutEngine()
     336             : {
     337        7482 :     hb_face_destroy(mpHbFace);
     338       14964 : }
     339             : 
     340             : struct HbScriptRun
     341             : {
     342             :     int32_t mnMin;
     343             :     int32_t mnEnd;
     344             :     hb_script_t maScript;
     345             : 
     346     2140250 :     HbScriptRun(int32_t nMin, int32_t nEnd, UScriptCode aScript)
     347             :     : mnMin(nMin), mnEnd(nEnd),
     348     2140250 :       maScript(hb_icu_script_to_script(aScript))
     349     2140250 :     {}
     350             : };
     351             : 
     352             : typedef std::vector<HbScriptRun> HbScriptRuns;
     353             : 
     354     2156373 : bool HbLayoutEngine::layout(ServerFontLayout& rLayout, ImplLayoutArgs& rArgs)
     355             : {
     356     2156373 :     ServerFont& rFont = rLayout.GetServerFont();
     357     2156373 :     FT_Face aFtFace = rFont.GetFtFace();
     358             : 
     359             :     SAL_INFO("vcl.harfbuzz", "layout(" << this << ",rArgs=" << rArgs << ")");
     360             : 
     361     2156373 :     static hb_font_funcs_t* pHbFontFuncs = getFontFuncs();
     362             : 
     363     2156373 :     hb_font_t *pHbFont = hb_font_create(mpHbFace);
     364     2156373 :     hb_font_set_funcs(pHbFont, pHbFontFuncs, &rFont, NULL);
     365             :     hb_font_set_scale(pHbFont,
     366     2156373 :             ((uint64_t) aFtFace->size->metrics.x_scale * (uint64_t) mnUnitsPerEM) >> 16,
     367     4312746 :             ((uint64_t) aFtFace->size->metrics.y_scale * (uint64_t) mnUnitsPerEM) >> 16);
     368     2156373 :     hb_font_set_ppem(pHbFont, aFtFace->size->metrics.x_ppem, aFtFace->size->metrics.y_ppem);
     369             : 
     370             :     // allocate temporary arrays, note: round to even
     371     2156373 :     int nGlyphCapacity = (3 * (rArgs.mnEndCharPos - rArgs.mnMinCharPos) | 15) + 1;
     372             : 
     373     2156373 :     rLayout.Reserve(nGlyphCapacity);
     374             : 
     375     2156373 :     vcl::ScriptRun aScriptRun(reinterpret_cast<const UChar *>(rArgs.mpStr), rArgs.mnLength);
     376             : 
     377     2156373 :     Point aCurrPos(0, 0);
     378             :     while (true)
     379             :     {
     380             :         int nBidiMinRunPos, nBidiEndRunPos;
     381             :         bool bRightToLeft;
     382     4296109 :         if (!rArgs.GetNextRun(&nBidiMinRunPos, &nBidiEndRunPos, &bRightToLeft))
     383     2156373 :             break;
     384             : 
     385             :         // Find script subruns.
     386     2139736 :         int nCurrentPos = nBidiMinRunPos;
     387     2139736 :         HbScriptRuns aScriptSubRuns;
     388     2139736 :         while (aScriptRun.next())
     389             :         {
     390     2140328 :             if (aScriptRun.getScriptStart() <= nCurrentPos && aScriptRun.getScriptEnd() > nCurrentPos)
     391     2139736 :                 break;
     392             :         }
     393             : 
     394     6419722 :         while (nCurrentPos < nBidiEndRunPos)
     395             :         {
     396     2140250 :             int32_t nMinRunPos = nCurrentPos;
     397     2140250 :             int32_t nEndRunPos = std::min(aScriptRun.getScriptEnd(), nBidiEndRunPos);
     398     2140250 :             HbScriptRun aRun(nMinRunPos, nEndRunPos, aScriptRun.getScriptCode());
     399     2140250 :             aScriptSubRuns.push_back(aRun);
     400             : 
     401     2140250 :             nCurrentPos = nEndRunPos;
     402     2140250 :             aScriptRun.next();
     403             :         }
     404             : 
     405             :         // RTL subruns should be reversed to ensure that final glyph order is
     406             :         // correct.
     407     2139736 :         if (bRightToLeft)
     408         793 :             std::reverse(aScriptSubRuns.begin(), aScriptSubRuns.end());
     409             : 
     410     2139736 :         aScriptRun.reset();
     411             : 
     412     4279986 :         for (HbScriptRuns::iterator it = aScriptSubRuns.begin(); it != aScriptSubRuns.end(); ++it)
     413             :         {
     414     2140250 :             int nMinRunPos = it->mnMin;
     415     2140250 :             int nEndRunPos = it->mnEnd;
     416     2140250 :             int nRunLen = nEndRunPos - nMinRunPos;
     417     2140250 :             maHbScript = it->maScript;
     418             : 
     419     2140250 :             OString sLanguage = OUStringToOString(rArgs.maLanguageTag.getLanguage(), RTL_TEXTENCODING_UTF8);
     420             : 
     421     2140250 :             static hb_unicode_funcs_t* pHbUnicodeFuncs = getUnicodeFuncs();
     422             : 
     423     2140250 :             int nHbFlags = HB_BUFFER_FLAGS_DEFAULT;
     424     2140250 :             if (nMinRunPos == 0)
     425     1712843 :                 nHbFlags |= HB_BUFFER_FLAG_BOT; /* Beginning-of-text */
     426     2140250 :             if (nEndRunPos == rArgs.mnLength)
     427     1792542 :                 nHbFlags |= HB_BUFFER_FLAG_EOT; /* End-of-text */
     428             : 
     429     2140250 :             hb_buffer_t *pHbBuffer = hb_buffer_create();
     430     2140250 :             hb_buffer_set_unicode_funcs(pHbBuffer, pHbUnicodeFuncs);
     431     2140250 :             hb_buffer_set_direction(pHbBuffer, bRightToLeft ? HB_DIRECTION_RTL: HB_DIRECTION_LTR);
     432     2140250 :             hb_buffer_set_script(pHbBuffer, maHbScript);
     433     2140250 :             hb_buffer_set_language(pHbBuffer, hb_language_from_string(sLanguage.getStr(), -1));
     434     2140250 :             hb_buffer_set_flags(pHbBuffer, (hb_buffer_flags_t) nHbFlags);
     435     2140250 :             hb_buffer_add_utf16(pHbBuffer, rArgs.mpStr, rArgs.mnLength, nMinRunPos, nRunLen);
     436     2140250 :             hb_shape(pHbFont, pHbBuffer, NULL, 0);
     437             : 
     438     2140250 :             int nRunGlyphCount = hb_buffer_get_length(pHbBuffer);
     439     2140250 :             hb_glyph_info_t *pHbGlyphInfos = hb_buffer_get_glyph_infos(pHbBuffer, NULL);
     440     2140250 :             hb_glyph_position_t *pHbPositions = hb_buffer_get_glyph_positions(pHbBuffer, NULL);
     441             : 
     442    43670710 :             for (int i = 0; i < nRunGlyphCount; ++i) {
     443    41530460 :                 int32_t nGlyphIndex = pHbGlyphInfos[i].codepoint;
     444    41530460 :                 int32_t nCharPos = pHbGlyphInfos[i].cluster;
     445             : 
     446             :                 // if needed request glyph fallback by updating LayoutArgs
     447    41530460 :                 if (!nGlyphIndex)
     448             :                 {
     449        2344 :                     rLayout.setNeedFallback(rArgs, nCharPos, bRightToLeft);
     450        2344 :                     if (SAL_LAYOUT_FOR_FALLBACK & rArgs.mnFlags)
     451          52 :                         continue;
     452             :                 }
     453             : 
     454             :                 // apply vertical flags and glyph substitution
     455             :                 // XXX: Use HB_DIRECTION_TTB above and apply whatever flags magic
     456             :                 // FixupGlyphIndex() is doing, minus the GSUB part.
     457    41530408 :                 if (nCharPos >= 0)
     458             :                 {
     459    41530408 :                     sal_UCS4 aChar = rArgs.mpStr[nCharPos];
     460    41530408 :                     nGlyphIndex = rFont.FixupGlyphIndex(nGlyphIndex, aChar);
     461             :                 }
     462             : 
     463    41530408 :                 bool bInCluster = false;
     464    41530408 :                 if (i > 0 && pHbGlyphInfos[i].cluster == pHbGlyphInfos[i - 1].cluster)
     465          16 :                     bInCluster = true;
     466             : 
     467    41530408 :                 long nGlyphFlags = 0;
     468    41530408 :                 if (bRightToLeft)
     469        1351 :                     nGlyphFlags |= GlyphItem::IS_RTL_GLYPH;
     470             : 
     471    41530408 :                 if (bInCluster)
     472          16 :                     nGlyphFlags |= GlyphItem::IS_IN_CLUSTER;
     473             : 
     474             :                 // The whole IS_DIACRITIC concept is a stupid hack that was
     475             :                 // introduced ages ago to work around the utter brokenness of the
     476             :                 // way justification adjustments are applied (the DXArray fiasco).
     477             :                 // Since it is such a stupid hack, there is no sane way to directly
     478             :                 // map to concepts of the "outside" world, so we do some rather
     479             :                 // ugly hacks:
     480             :                 // * If the font has a GDEF table, we check for glyphs with mark
     481             :                 //   glyph class which is sensible, except that some fonts
     482             :                 //   (fdo#70968) assign mark class to spacing marks (which is wrong
     483             :                 //   but usually harmless), so we try to sniff what HarfBuzz thinks
     484             :                 //   about this glyph by checking if it gives it a zero advance
     485             :                 //   width.
     486             :                 // * If the font has no GDEF table, we just check if the glyph has
     487             :                 //   zero advance width, but this is stupid and can be wrong. A
     488             :                 //   better way would to check the character's Unicode combining
     489             :                 //   class, but unfortunately glyph gives combining marks the
     490             :                 //   cluster value of its base character, so nCharPos will be
     491             :                 //   pointing to the wrong character (but HarfBuzz might change
     492             :                 //   this in the future).
     493    41530408 :                 bool bDiacritic = false;
     494    41530408 :                 if (hb_ot_layout_has_glyph_classes(mpHbFace))
     495             :                 {
     496             :                     // the font has GDEF table
     497    41470068 :                     bool bMark = hb_ot_layout_get_glyph_class(mpHbFace, nGlyphIndex) == HB_OT_LAYOUT_GLYPH_CLASS_MARK;
     498    41470068 :                     if (bMark && pHbPositions[i].x_advance == 0)
     499          16 :                         bDiacritic = true;
     500             :                 }
     501             :                 else
     502             :                 {
     503             :                     // the font lacks GDEF table
     504       60340 :                     if (pHbPositions[i].x_advance == 0)
     505           8 :                         bDiacritic = true;
     506             :                 }
     507             : 
     508    41530408 :                 if (bDiacritic)
     509          24 :                     nGlyphFlags |= GlyphItem::IS_DIACRITIC;
     510             : 
     511    41530408 :                 int32_t nXOffset =  pHbPositions[i].x_offset >> 6;
     512    41530408 :                 int32_t nYOffset =  pHbPositions[i].y_offset >> 6;
     513    41530408 :                 int32_t nXAdvance = pHbPositions[i].x_advance >> 6;
     514    41530408 :                 int32_t nYAdvance = pHbPositions[i].y_advance >> 6;
     515             : 
     516    41530408 :                 Point aNewPos = Point(aCurrPos.X() + nXOffset, -(aCurrPos.Y() + nYOffset));
     517    41530408 :                 const GlyphItem aGI(nCharPos, nGlyphIndex, aNewPos, nGlyphFlags, nXAdvance, nXOffset);
     518    41530408 :                 rLayout.AppendGlyph(aGI);
     519             : 
     520    41530408 :                 aCurrPos.X() += nXAdvance;
     521    41530408 :                 aCurrPos.Y() += nYAdvance;
     522             :             }
     523             : 
     524     2140250 :             hb_buffer_destroy(pHbBuffer);
     525     2140250 :         }
     526     2139736 :     }
     527             : 
     528     2156373 :     hb_font_destroy(pHbFont);
     529             : 
     530             :     // sort glyphs in visual order
     531             :     // and then in logical order (e.g. diacritics after cluster start)
     532             :     // XXX: why?
     533     2156373 :     rLayout.SortGlyphItems();
     534             : 
     535             :     // determine need for kashida justification
     536     2156373 :     if((rArgs.mpDXArray || rArgs.mnLayoutWidth)
     537       58988 :     && ((maHbScript == HB_SCRIPT_ARABIC) || (maHbScript == HB_SCRIPT_SYRIAC)))
     538           0 :         rArgs.mnFlags |= SAL_LAYOUT_KASHIDA_JUSTIFICATON;
     539             : 
     540     2156373 :     return true;
     541             : }
     542             : 
     543     2156373 : ServerFontLayoutEngine* ServerFont::GetLayoutEngine()
     544             : {
     545             :     // find best layout engine for font, platform, script and language
     546     2156373 :     if (!mpLayoutEngine) {
     547        7482 :         mpLayoutEngine = new HbLayoutEngine(*this);
     548             :     }
     549     2156373 :     return mpLayoutEngine;
     550        1233 : }
     551             : 
     552             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10