diff options
Diffstat (limited to 'vcl/source/font/fontinstance.cxx')
-rw-r--r-- | vcl/source/font/fontinstance.cxx | 168 |
1 files changed, 168 insertions, 0 deletions
diff --git a/vcl/source/font/fontinstance.cxx b/vcl/source/font/fontinstance.cxx new file mode 100644 index 000000000..40e334bd6 --- /dev/null +++ b/vcl/source/font/fontinstance.cxx @@ -0,0 +1,168 @@ +/* -*- 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 <hb-ot.h> +#include <hb-graphite2.h> + +#include <fontinstance.hxx> +#include <impfontcache.hxx> + +#include <PhysicalFontFace.hxx> + +// extend std namespace to add custom hash needed for LogicalFontInstance + +namespace std +{ + template <> struct hash< pair< sal_UCS4, FontWeight > > + { + size_t operator()(const pair< sal_UCS4, FontWeight >& rData) const + { + std::size_t seed = 0; + boost::hash_combine(seed, rData.first); + boost::hash_combine(seed, rData.second); + return seed; + } + }; +} + + +LogicalFontInstance::LogicalFontInstance(const PhysicalFontFace& rFontFace, const FontSelectPattern& rFontSelData ) + : mxFontMetric( new ImplFontMetricData( rFontSelData )) + , mpConversion( nullptr ) + , mnLineHeight( 0 ) + , mnOwnOrientation( 0 ) + , mnOrientation( 0 ) + , mbInit( false ) + , mpFontCache( nullptr ) + , m_aFontSelData(rFontSelData) + , m_pHbFont(nullptr) + , m_nAveWidthFactor(1.0f) + , m_pFontFace(&const_cast<PhysicalFontFace&>(rFontFace)) +{ +} + +LogicalFontInstance::~LogicalFontInstance() +{ + mpUnicodeFallbackList.reset(); + mpFontCache = nullptr; + mxFontMetric = nullptr; + + if (m_pHbFont) + hb_font_destroy(m_pHbFont); +} + +hb_font_t* LogicalFontInstance::InitHbFont(hb_face_t* pHbFace) +{ + assert(pHbFace); + hb_font_t* pHbFont = hb_font_create(pHbFace); + unsigned int nUPEM = hb_face_get_upem(pHbFace); + hb_font_set_scale(pHbFont, nUPEM, nUPEM); + hb_ot_font_set_funcs(pHbFont); + // hb_font_t keeps a reference to hb_face_t, so destroy this one. + hb_face_destroy(pHbFace); + return pHbFont; +} + +int LogicalFontInstance::GetKashidaWidth() +{ + hb_font_t* pHbFont = GetHbFont(); + hb_position_t nWidth = 0; + hb_codepoint_t nIndex = 0; + + if (hb_font_get_glyph(pHbFont, 0x0640, 0, &nIndex)) + { + double nXScale = 0; + GetScale(&nXScale, nullptr); + nWidth = hb_font_get_glyph_h_advance(pHbFont, nIndex) * nXScale; + } + + return nWidth; +} + +void LogicalFontInstance::GetScale(double* nXScale, double* nYScale) +{ + hb_face_t* pHbFace = hb_font_get_face(GetHbFont()); + unsigned int nUPEM = hb_face_get_upem(pHbFace); + + double nHeight(m_aFontSelData.mnHeight); + + // On Windows, mnWidth is relative to average char width not font height, + // and we need to keep it that way for GDI to correctly scale the glyphs. + // Here we compensate for this so that HarfBuzz gives us the correct glyph + // positions. + double nWidth(m_aFontSelData.mnWidth ? m_aFontSelData.mnWidth * m_nAveWidthFactor : nHeight); + + if (nYScale) + *nYScale = nHeight / nUPEM; + + if (nXScale) + *nXScale = nWidth / nUPEM; +} + +void LogicalFontInstance::AddFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName ) +{ + if( !mpUnicodeFallbackList ) + mpUnicodeFallbackList.reset(new UnicodeFallbackList); + (*mpUnicodeFallbackList)[ std::pair< sal_UCS4, FontWeight >(cChar,eWeight) ] = rFontName; +} + +bool LogicalFontInstance::GetFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, OUString* pFontName ) const +{ + if( !mpUnicodeFallbackList ) + return false; + + UnicodeFallbackList::const_iterator it = mpUnicodeFallbackList->find( std::pair< sal_UCS4, FontWeight >(cChar,eWeight) ); + if( it == mpUnicodeFallbackList->end() ) + return false; + + *pFontName = (*it).second; + return true; +} + +void LogicalFontInstance::IgnoreFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName ) +{ + UnicodeFallbackList::iterator it = mpUnicodeFallbackList->find( std::pair< sal_UCS4,FontWeight >(cChar,eWeight) ); + if( it == mpUnicodeFallbackList->end() ) + return; + if( (*it).second == rFontName ) + mpUnicodeFallbackList->erase( it ); +} + +bool LogicalFontInstance::GetGlyphBoundRect(sal_GlyphId nID, tools::Rectangle &rRect, bool bVertical) const +{ + if (mpFontCache && mpFontCache->GetCachedGlyphBoundRect(this, nID, rRect)) + return true; + + bool res = ImplGetGlyphBoundRect(nID, rRect, bVertical); + if (mpFontCache && res) + mpFontCache->CacheGlyphBoundRect(this, nID, rRect); + return res; +} + +bool LogicalFontInstance::IsGraphiteFont() +{ + if (!m_xbIsGraphiteFont) + { + m_xbIsGraphiteFont = hb_graphite2_face_get_gr_face(hb_font_get_face(GetHbFont())) != nullptr; + } + return *m_xbIsGraphiteFont; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |