summaryrefslogtreecommitdiff
path: root/vcl/generic/glyphs/gcach_layout.cxx
diff options
context:
space:
mode:
authorChris Sherlock <chris.sherlock79@gmail.com>2016-01-11 13:41:05 +1100
committerChris Sherlock <chris.sherlock79@gmail.com>2016-01-11 03:30:42 +0000
commit09a1566bf18cdf98b111d4979e4f4ad52ce65b07 (patch)
tree8ae3d9283dacd2c94214f3aeda853b73f403f511 /vcl/generic/glyphs/gcach_layout.cxx
parent557a6d20080e6f4d95db9e5b4dff87f3e51ac054 (diff)
vcl: move all glyph files from generic to unx
All the files in glyph are only used by Unix based systems, with the exception of OS X. Therefore, it's not really "generic" as in "used across all platforms" but is generic as in "used in all Unix-based systems". Change-Id: Id89c09df74f0ddafee5c88c55bac4c35f9b23ef8 Reviewed-on: https://gerrit.libreoffice.org/21312 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Chris Sherlock <chris.sherlock79@gmail.com>
Diffstat (limited to 'vcl/generic/glyphs/gcach_layout.cxx')
-rw-r--r--vcl/generic/glyphs/gcach_layout.cxx621
1 files changed, 0 insertions, 621 deletions
diff --git a/vcl/generic/glyphs/gcach_layout.cxx b/vcl/generic/glyphs/gcach_layout.cxx
deleted file mode 100644
index 70ac1901f09d..000000000000
--- a/vcl/generic/glyphs/gcach_layout.cxx
+++ /dev/null
@@ -1,621 +0,0 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
-/*
- * This file is part of the LibreOffice project.
- *
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/.
- *
- * This file incorporates work covered by the following license notice:
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed
- * with this work for additional information regarding copyright
- * ownership. The ASF licenses this file to you under the Apache
- * License, Version 2.0 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.apache.org/licenses/LICENSE-2.0 .
- */
-
-#include "unx/freetype_glyphcache.hxx"
-#include <sallayout.hxx>
-#include <salgdi.hxx>
-#include <scrptrun.h>
-
-#include <i18nlangtag/mslangid.hxx>
-
-#include <vcl/svapp.hxx>
-#include <vcl/unohelp.hxx>
-
-#include <rtl/instance.hxx>
-
-#include <hb-icu.h>
-#include <hb-ot.h>
-
-#include <com/sun/star/i18n/CharacterIteratorMode.hpp>
-
-#ifndef HB_VERSION_ATLEAST
-#define HB_VERSION_ATLEAST(a,b,c) 0
-#endif
-
-// layout implementation for ServerFont
-ServerFontLayout::ServerFontLayout( ServerFont& rFont )
-: mrServerFont( rFont )
-{
-}
-
-void ServerFontLayout::DrawText( SalGraphics& rSalGraphics ) const
-{
- rSalGraphics.DrawServerFontLayout( *this );
-}
-
-bool ServerFontLayout::LayoutText( ImplLayoutArgs& rArgs )
-{
- return mrServerFont.GetLayoutEngine()->Layout(*this, rArgs);
-}
-
-void ServerFontLayout::AdjustLayout( ImplLayoutArgs& rArgs )
-{
- GenericSalLayout::AdjustLayout( rArgs );
-
- // apply asian kerning if the glyphs are not already formatted
- if( (rArgs.mnFlags & SalLayoutFlags::KerningAsian)
- && !(rArgs.mnFlags & SalLayoutFlags::Vertical) )
- if( (rArgs.mpDXArray != nullptr) || (rArgs.mnLayoutWidth != 0) )
- ApplyAsianKerning(rArgs.mrStr);
-
- // insert kashidas where requested by the formatting array
- if( (rArgs.mnFlags & SalLayoutFlags::KashidaJustification) && rArgs.mpDXArray )
- {
- int nKashidaIndex = mrServerFont.GetGlyphIndex( 0x0640 );
- if( nKashidaIndex != 0 )
- {
- const GlyphMetric& rGM = mrServerFont.GetGlyphMetric( nKashidaIndex );
- KashidaJustify( nKashidaIndex, rGM.GetCharWidth() );
- // TODO: kashida-GSUB/GPOS
- }
- }
-}
-
-void ServerFontLayout::SetNeedFallback(ImplLayoutArgs& rArgs, sal_Int32 nCharPos,
- bool bRightToLeft)
-{
- if (nCharPos < 0)
- return;
-
- using namespace ::com::sun::star;
-
- if (!mxBreak.is())
- mxBreak = vcl::unohelper::CreateBreakIterator();
-
- lang::Locale aLocale(rArgs.maLanguageTag.getLocale());
-
- //if position nCharPos is missing in the font, grab the entire grapheme and
- //mark all glyphs as missing so the whole thing is rendered with the same
- //font
- sal_Int32 nDone;
- sal_Int32 nGraphemeStartPos =
- mxBreak->previousCharacters(rArgs.mrStr, nCharPos+1, aLocale,
- i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
- sal_Int32 nGraphemeEndPos =
- mxBreak->nextCharacters(rArgs.mrStr, nCharPos, aLocale,
- i18n::CharacterIteratorMode::SKIPCELL, 1, nDone);
-
- rArgs.NeedFallback(nGraphemeStartPos, nGraphemeEndPos, bRightToLeft);
-}
-
-std::ostream &operator <<(std::ostream& s, ServerFont* pFont)
-{
-#ifndef SAL_LOG_INFO
- (void) pFont;
-#else
- FT_Face aFace = pFont->GetFtFace();
- const char* pName = FT_Get_Postscript_Name(aFace);
- if (pName)
- s << pName;
- else
- s << pFont->GetFontFileName();
-#endif
- return s;
-}
-
-static hb_blob_t *getFontTable(hb_face_t* /*face*/, hb_tag_t nTableTag, void* pUserData)
-{
- char pTagName[5];
- pTagName[0] = (char)(nTableTag >> 24);
- pTagName[1] = (char)(nTableTag >> 16);
- pTagName[2] = (char)(nTableTag >> 8);
- pTagName[3] = (char)(nTableTag);
- pTagName[4] = 0;
-
- ServerFont* pFont = static_cast<ServerFont*>(pUserData);
-
- SAL_INFO("vcl.harfbuzz", "getFontTable(" << pFont << ", " << pTagName << ")");
-
- sal_uLong nLength;
- const unsigned char* pBuffer = pFont->GetTable(pTagName, &nLength);
-
- hb_blob_t* pBlob = nullptr;
- if (pBuffer != nullptr)
- pBlob = hb_blob_create(reinterpret_cast<const char*>(pBuffer), nLength, HB_MEMORY_MODE_READONLY, const_cast<unsigned char *>(pBuffer), nullptr);
-
- return pBlob;
-}
-
-static hb_bool_t getFontGlyph(hb_font_t* /*font*/, void* pFontData,
- hb_codepoint_t ch, hb_codepoint_t vs,
- hb_codepoint_t* nGlyphIndex,
- void* /*pUserData*/)
-{
- ServerFont* pFont = static_cast<ServerFont*>(pFontData);
- *nGlyphIndex = pFont->GetRawGlyphIndex(ch, vs);
-
- // tdf#89231 if the font is missing non-breaking space, then use a normal space
- if (*nGlyphIndex == 0 && ch == 0x202F && !vs)
- *nGlyphIndex = pFont->GetRawGlyphIndex(' ');
-
- return *nGlyphIndex != 0;
-}
-
-static hb_position_t getGlyphAdvanceH(hb_font_t* /*font*/, void* pFontData,
- hb_codepoint_t nGlyphIndex,
- void* /*pUserData*/)
-{
- ServerFont* pFont = static_cast<ServerFont*>(pFontData);
- const GlyphMetric& rGM = pFont->GetGlyphMetric(nGlyphIndex);
- return rGM.GetCharWidth() << 6;
-}
-
-#if !HB_VERSION_ATLEAST(1, 1, 2)
-static hb_position_t getGlyphAdvanceV(hb_font_t* /*font*/, void* /*pFontData*/,
- hb_codepoint_t /*nGlyphIndex*/,
- void* /*pUserData*/)
-{
- // XXX: vertical metrics
- return 0;
-}
-
-static hb_bool_t getGlyphOriginH(hb_font_t* /*font*/, void* /*pFontData*/,
- hb_codepoint_t /*nGlyphIndex*/,
- hb_position_t* /*x*/, hb_position_t* /*y*/,
- void* /*pUserData*/)
-{
- // the horizontal origin is always (0, 0)
- return true;
-}
-
-static hb_bool_t getGlyphOriginV(hb_font_t* /*font*/, void* /*pFontData*/,
- hb_codepoint_t /*nGlyphIndex*/,
- hb_position_t* /*x*/, hb_position_t* /*y*/,
- void* /*pUserData*/)
-{
- // XXX: vertical origin
- return true;
-}
-#endif
-
-static hb_position_t getGlyphKerningH(hb_font_t* /*font*/, void* pFontData,
- hb_codepoint_t nGlyphIndex1, hb_codepoint_t nGlyphIndex2,
- void* /*pUserData*/)
-{
- // This callback is for old style 'kern' table, GPOS kerning is handled by HarfBuzz directly
-
- ServerFont* pFont = static_cast<ServerFont*>(pFontData);
- FT_Face aFace = pFont->GetFtFace();
-
- SAL_INFO("vcl.harfbuzz", "getGlyphKerningH(" << pFont << ", " << nGlyphIndex1 << ", " << nGlyphIndex2 << ")");
-
- FT_Error error;
- FT_Vector kerning;
- hb_position_t ret;
-
- error = FT_Get_Kerning(aFace, nGlyphIndex1, nGlyphIndex2, FT_KERNING_DEFAULT, &kerning);
- if (error)
- ret = 0;
- else
- ret = kerning.x;
-
- return ret;
-}
-
-#if !HB_VERSION_ATLEAST(1, 1, 2)
-static hb_position_t getGlyphKerningV(hb_font_t* /*font*/, void* /*pFontData*/,
- hb_codepoint_t /*nGlyphIndex1*/, hb_codepoint_t /*nGlyphIndex2*/,
- void* /*pUserData*/)
-{
- // XXX vertical kerning
- return 0;
-}
-#endif
-
-static hb_bool_t getGlyphExtents(hb_font_t* /*font*/, void* pFontData,
- hb_codepoint_t nGlyphIndex,
- hb_glyph_extents_t* pExtents,
- void* /*pUserData*/)
-{
- ServerFont* pFont = static_cast<ServerFont*>(pFontData);
- FT_Face aFace = pFont->GetFtFace();
-
- SAL_INFO("vcl.harfbuzz", "getGlyphExtents(" << pFont << ", " << nGlyphIndex << ")");
-
- FT_Error error;
- error = FT_Load_Glyph(aFace, nGlyphIndex, FT_LOAD_DEFAULT);
- if (!error)
- {
- pExtents->x_bearing = aFace->glyph->metrics.horiBearingX;
- pExtents->y_bearing = aFace->glyph->metrics.horiBearingY;
- pExtents->width = aFace->glyph->metrics.width;
- pExtents->height = -aFace->glyph->metrics.height;
- }
-
- return !error;
-}
-
-static hb_bool_t getGlyphContourPoint(hb_font_t* /*font*/, void* pFontData,
- hb_codepoint_t nGlyphIndex, unsigned int nPointIndex,
- hb_position_t *x, hb_position_t *y,
- void* /*pUserData*/)
-{
- bool ret = false;
- ServerFont* pFont = static_cast<ServerFont*>(pFontData);
- FT_Face aFace = pFont->GetFtFace();
-
- SAL_INFO("vcl.harfbuzz", "getGlyphContourPoint(" << pFont << ", " << nGlyphIndex << ", " << nPointIndex << ")");
-
- FT_Error error;
- error = FT_Load_Glyph(aFace, nGlyphIndex, FT_LOAD_DEFAULT);
- if (!error)
- {
- if (aFace->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
- {
- if (nPointIndex < (unsigned int) aFace->glyph->outline.n_points)
- {
- *x = aFace->glyph->outline.points[nPointIndex].x;
- *y = aFace->glyph->outline.points[nPointIndex].y;
- ret = true;
- }
- }
- }
-
- return ret;
-}
-
-static hb_font_funcs_t* getFontFuncs()
-{
- static hb_font_funcs_t* funcs = hb_font_funcs_create();
-
- hb_font_funcs_set_glyph_func (funcs, getFontGlyph, nullptr, nullptr);
- hb_font_funcs_set_glyph_h_advance_func (funcs, getGlyphAdvanceH, nullptr, nullptr);
- hb_font_funcs_set_glyph_h_kerning_func (funcs, getGlyphKerningH, nullptr, nullptr);
- hb_font_funcs_set_glyph_extents_func (funcs, getGlyphExtents, nullptr, nullptr);
- hb_font_funcs_set_glyph_contour_point_func (funcs, getGlyphContourPoint, nullptr, nullptr);
-#if !HB_VERSION_ATLEAST(1, 1, 2)
- hb_font_funcs_set_glyph_v_advance_func (funcs, getGlyphAdvanceV, nullptr, nullptr);
- hb_font_funcs_set_glyph_h_origin_func (funcs, getGlyphOriginH, nullptr, nullptr);
- hb_font_funcs_set_glyph_v_origin_func (funcs, getGlyphOriginV, nullptr, nullptr);
- hb_font_funcs_set_glyph_v_kerning_func (funcs, getGlyphKerningV, nullptr, nullptr);
-#endif
-
- return funcs;
-}
-
-#if !HB_VERSION_ATLEAST(1, 1, 0)
-// Disabled Unicode compatibility decomposition, see fdo#66715
-static unsigned int unicodeDecomposeCompatibility(hb_unicode_funcs_t* /*ufuncs*/,
- hb_codepoint_t /*u*/,
- hb_codepoint_t* /*decomposed*/,
- void* /*user_data*/)
-{
- return 0;
-}
-
-static hb_unicode_funcs_t* getUnicodeFuncs()
-{
- static hb_unicode_funcs_t* ufuncs = hb_unicode_funcs_create(hb_icu_get_unicode_funcs());
- hb_unicode_funcs_set_decompose_compatibility_func(ufuncs, unicodeDecomposeCompatibility, nullptr, nullptr);
- return ufuncs;
-}
-#endif
-
-class HbLayoutEngine : public ServerFontLayoutEngine
-{
-private:
- hb_script_t maHbScript;
- hb_face_t* mpHbFace;
- int mnUnitsPerEM;
-
-public:
- explicit HbLayoutEngine(ServerFont&);
- virtual ~HbLayoutEngine();
-
- virtual bool Layout(ServerFontLayout&, ImplLayoutArgs&) override;
-};
-
-HbLayoutEngine::HbLayoutEngine(ServerFont& rServerFont)
-: maHbScript(HB_SCRIPT_INVALID),
- mpHbFace(nullptr),
- mnUnitsPerEM(0)
-{
- FT_Face aFtFace = rServerFont.GetFtFace();
- mnUnitsPerEM = rServerFont.GetEmUnits();
-
- mpHbFace = hb_face_create_for_tables(getFontTable, &rServerFont, nullptr);
- hb_face_set_index(mpHbFace, aFtFace->face_index);
- hb_face_set_upem(mpHbFace, mnUnitsPerEM);
-}
-
-HbLayoutEngine::~HbLayoutEngine()
-{
- hb_face_destroy(mpHbFace);
-}
-
-struct HbScriptRun
-{
- int32_t mnMin;
- int32_t mnEnd;
- hb_script_t maScript;
-
- HbScriptRun(int32_t nMin, int32_t nEnd, UScriptCode aScript)
- : mnMin(nMin), mnEnd(nEnd),
- maScript(hb_icu_script_to_script(aScript))
- {}
-};
-
-typedef std::vector<HbScriptRun> HbScriptRuns;
-
-namespace vcl {
- struct Run
- {
- int32_t nStart;
- int32_t nEnd;
- UScriptCode nCode;
- Run(int32_t nStart_, int32_t nEnd_, UScriptCode nCode_)
- : nStart(nStart_), nEnd(nEnd_), nCode(nCode_)
- {}
- };
-
- class TextLayoutCache
- {
- public:
- std::vector<vcl::Run> runs;
- TextLayoutCache(sal_Unicode const* pStr, sal_Int32 const nEnd)
- {
- vcl::ScriptRun aScriptRun(
- reinterpret_cast<const UChar *>(pStr),
- nEnd);
- while (aScriptRun.next())
- {
- runs.push_back(Run(aScriptRun.getScriptStart(),
- aScriptRun.getScriptEnd(), aScriptRun.getScriptCode()));
- }
- }
- };
-}
-
-std::shared_ptr<vcl::TextLayoutCache> ServerFontLayout::CreateTextLayoutCache(
- OUString const& rString) const
-{
- return std::make_shared<vcl::TextLayoutCache>(rString.getStr(), rString.getLength());
-}
-
-bool HbLayoutEngine::Layout(ServerFontLayout& rLayout, ImplLayoutArgs& rArgs)
-{
- ServerFont& rFont = rLayout.GetServerFont();
- FT_Face aFtFace = rFont.GetFtFace();
-
- SAL_INFO("vcl.harfbuzz", "layout(" << this << ",rArgs=" << rArgs << ")");
-
- static hb_font_funcs_t* pHbFontFuncs = getFontFuncs();
-
- hb_font_t *pHbFont = hb_font_create(mpHbFace);
- hb_font_set_funcs(pHbFont, pHbFontFuncs, &rFont, nullptr);
- hb_font_set_scale(pHbFont,
- ((uint64_t) aFtFace->size->metrics.x_scale * (uint64_t) mnUnitsPerEM) >> 16,
- ((uint64_t) aFtFace->size->metrics.y_scale * (uint64_t) mnUnitsPerEM) >> 16);
- hb_font_set_ppem(pHbFont, aFtFace->size->metrics.x_ppem, aFtFace->size->metrics.y_ppem);
-
- // allocate temporary arrays, note: round to even
- int nGlyphCapacity = (3 * (rArgs.mnEndCharPos - rArgs.mnMinCharPos) | 15) + 1;
- int32_t nVirtAdv = int32_t(aFtFace->size->metrics.height*rFont.GetStretch())>>6;
-
- rLayout.Reserve(nGlyphCapacity);
-
- const int nLength = rArgs.mrStr.getLength();
- const sal_Unicode *pStr = rArgs.mrStr.getStr();
-
- std::unique_ptr<vcl::TextLayoutCache> pNewScriptRun;
- vcl::TextLayoutCache const* pTextLayout;
- if (rArgs.m_pTextLayoutCache)
- {
- pTextLayout = rArgs.m_pTextLayoutCache; // use cache!
- }
- else
- {
- pNewScriptRun.reset(new vcl::TextLayoutCache(pStr, rArgs.mnEndCharPos));
- pTextLayout = pNewScriptRun.get();
- }
-
- Point aCurrPos(0, 0);
- while (true)
- {
- int nBidiMinRunPos, nBidiEndRunPos;
- bool bRightToLeft;
- if (!rArgs.GetNextRun(&nBidiMinRunPos, &nBidiEndRunPos, &bRightToLeft))
- break;
-
- // Find script subruns.
- int nCurrentPos = nBidiMinRunPos;
- HbScriptRuns aScriptSubRuns;
- size_t k = 0;
- for (; k < pTextLayout->runs.size(); ++k)
- {
- vcl::Run const& rRun(pTextLayout->runs[k]);
- if (rRun.nStart <= nCurrentPos && nCurrentPos < rRun.nEnd)
- {
- break;
- }
- }
-
- while (nCurrentPos < nBidiEndRunPos && k < pTextLayout->runs.size())
- {
- int32_t nMinRunPos = nCurrentPos;
- int32_t nEndRunPos = std::min(pTextLayout->runs[k].nEnd, nBidiEndRunPos);
- HbScriptRun aRun(nMinRunPos, nEndRunPos, pTextLayout->runs[k].nCode);
- aScriptSubRuns.push_back(aRun);
-
- nCurrentPos = nEndRunPos;
- ++k;
- }
-
- // RTL subruns should be reversed to ensure that final glyph order is
- // correct.
- if (bRightToLeft)
- std::reverse(aScriptSubRuns.begin(), aScriptSubRuns.end());
-
- for (HbScriptRuns::iterator it = aScriptSubRuns.begin(); it != aScriptSubRuns.end(); ++it)
- {
- int nMinRunPos = it->mnMin;
- int nEndRunPos = it->mnEnd;
- int nRunLen = nEndRunPos - nMinRunPos;
- maHbScript = it->maScript;
- // hb_language_from_string() accept ISO639-3 language tag except for Chinese.
- LanguageTag &rTag = rArgs.maLanguageTag;
- OString sLanguage = OUStringToOString( MsLangId::isChinese(rTag.getLanguageType()) ? rTag.getBcp47():rTag.getLanguage() , RTL_TEXTENCODING_UTF8 );
-
- int nHbFlags = HB_BUFFER_FLAGS_DEFAULT;
- if (nMinRunPos == 0)
- nHbFlags |= HB_BUFFER_FLAG_BOT; /* Beginning-of-text */
- if (nEndRunPos == nLength)
- nHbFlags |= HB_BUFFER_FLAG_EOT; /* End-of-text */
-
- hb_buffer_t *pHbBuffer = hb_buffer_create();
-#if !HB_VERSION_ATLEAST(1, 1, 0)
- static hb_unicode_funcs_t* pHbUnicodeFuncs = getUnicodeFuncs();
- hb_buffer_set_unicode_funcs(pHbBuffer, pHbUnicodeFuncs);
-#endif
- hb_buffer_set_direction(pHbBuffer, bRightToLeft ? HB_DIRECTION_RTL: HB_DIRECTION_LTR);
- hb_buffer_set_script(pHbBuffer, maHbScript);
- hb_buffer_set_language(pHbBuffer, hb_language_from_string(sLanguage.getStr(), -1));
- hb_buffer_set_flags(pHbBuffer, (hb_buffer_flags_t) nHbFlags);
- hb_buffer_add_utf16(
- pHbBuffer, reinterpret_cast<uint16_t const *>(pStr), nLength,
- nMinRunPos, nRunLen);
- hb_shape(pHbFont, pHbBuffer, nullptr, 0);
-
- int nRunGlyphCount = hb_buffer_get_length(pHbBuffer);
- hb_glyph_info_t *pHbGlyphInfos = hb_buffer_get_glyph_infos(pHbBuffer, nullptr);
- hb_glyph_position_t *pHbPositions = hb_buffer_get_glyph_positions(pHbBuffer, nullptr);
-
- for (int i = 0; i < nRunGlyphCount; ++i) {
- int32_t nGlyphIndex = pHbGlyphInfos[i].codepoint;
- int32_t nCharPos = pHbGlyphInfos[i].cluster;
-
- // if needed request glyph fallback by updating LayoutArgs
- if (!nGlyphIndex)
- {
- rLayout.SetNeedFallback(rArgs, nCharPos, bRightToLeft);
- if (SalLayoutFlags::ForFallback & rArgs.mnFlags)
- continue;
- }
-
- // apply vertical flags and glyph substitution
- // XXX: Use HB_DIRECTION_TTB above and apply whatever flags magic
- // FixupGlyphIndex() is doing, minus the GSUB part.
- if (nCharPos >= 0)
- {
- sal_UCS4 aChar = rArgs.mrStr[nCharPos];
- nGlyphIndex = rFont.FixupGlyphIndex(nGlyphIndex, aChar);
- }
-
- bool bInCluster = false;
- if (i > 0 && pHbGlyphInfos[i].cluster == pHbGlyphInfos[i - 1].cluster)
- bInCluster = true;
-
- long nGlyphFlags = 0;
- if (bRightToLeft)
- nGlyphFlags |= GlyphItem::IS_RTL_GLYPH;
-
- if (bInCluster)
- nGlyphFlags |= GlyphItem::IS_IN_CLUSTER;
-
- // The whole IS_DIACRITIC concept is a stupid hack that was
- // introduced ages ago to work around the utter brokenness of the
- // way justification adjustments are applied (the DXArray fiasco).
- // Since it is such a stupid hack, there is no sane way to directly
- // map to concepts of the "outside" world, so we do some rather
- // ugly hacks:
- // * If the font has a GDEF table, we check for glyphs with mark
- // glyph class which is sensible, except that some fonts
- // (fdo#70968) assign mark class to spacing marks (which is wrong
- // but usually harmless), so we try to sniff what HarfBuzz thinks
- // about this glyph by checking if it gives it a zero advance
- // width.
- // * If the font has no GDEF table, we just check if the glyph has
- // zero advance width, but this is stupid and can be wrong. A
- // better way would to check the character's Unicode combining
- // class, but unfortunately glyph gives combining marks the
- // cluster value of its base character, so nCharPos will be
- // pointing to the wrong character (but HarfBuzz might change
- // this in the future).
- bool bDiacritic = false;
- if (hb_ot_layout_has_glyph_classes(mpHbFace))
- {
- // the font has GDEF table
- bool bMark = hb_ot_layout_get_glyph_class(mpHbFace, nGlyphIndex) == HB_OT_LAYOUT_GLYPH_CLASS_MARK;
- if (bMark && pHbPositions[i].x_advance == 0)
- bDiacritic = true;
- }
- else
- {
- // the font lacks GDEF table
- if (pHbPositions[i].x_advance == 0)
- bDiacritic = true;
- }
-
- if (bDiacritic)
- nGlyphFlags |= GlyphItem::IS_DIACRITIC;
-
- int32_t nXOffset = pHbPositions[i].x_offset >> 6;
- int32_t nYOffset = pHbPositions[i].y_offset >> 6;
- int32_t nXAdvance = pHbPositions[i].x_advance >> 6;
- int32_t nYAdvance = pHbPositions[i].y_advance >> 6;
- if ( nGlyphIndex & GF_ROTMASK )
- nXAdvance = nVirtAdv;
-
- Point aNewPos = Point(aCurrPos.X() + nXOffset, -(aCurrPos.Y() + nYOffset));
- const GlyphItem aGI(nCharPos, nGlyphIndex, aNewPos, nGlyphFlags, nXAdvance, nXOffset, nYOffset);
- rLayout.AppendGlyph(aGI);
-
- aCurrPos.X() += nXAdvance;
- aCurrPos.Y() += nYAdvance;
- }
-
- hb_buffer_destroy(pHbBuffer);
- }
- }
-
- hb_font_destroy(pHbFont);
-
- // sort glyphs in visual order
- // and then in logical order (e.g. diacritics after cluster start)
- // XXX: why?
- rLayout.SortGlyphItems();
-
- // determine need for kashida justification
- if((rArgs.mpDXArray || rArgs.mnLayoutWidth)
- && ((maHbScript == HB_SCRIPT_ARABIC) || (maHbScript == HB_SCRIPT_SYRIAC)))
- rArgs.mnFlags |= SalLayoutFlags::KashidaJustification;
-
- return true;
-}
-
-ServerFontLayoutEngine* ServerFont::GetLayoutEngine()
-{
- // find best layout engine for font, platform, script and language
- if (!mpLayoutEngine) {
- mpLayoutEngine = new HbLayoutEngine(*this);
- }
- return mpLayoutEngine;
-}
-
-/* vim:set shiftwidth=4 softtabstop=4 expandtab: */