diff options
author | Norbert Thiebaud <nthiebaud@gmail.com> | 2014-03-20 00:22:26 -0500 |
---|---|---|
committer | Norbert Thiebaud <nthiebaud@gmail.com> | 2014-03-20 16:11:58 -0500 |
commit | 7260bcd68726739b5fe26b4d29a1de47e7b0f5a7 (patch) | |
tree | 360f470874da345bf0723cfd90684942824df739 /vcl/source/font/PhysicalFontFamily.cxx | |
parent | 7154b092a716d4d0041a8a563294511ec9e5dbc6 (diff) |
cosmetic: split PhysicalFontFamily/Collection out of outdev3.cxx
Change-Id: Iae8eb15413c0c069c14edd92c94ecb0113d9d371
Diffstat (limited to 'vcl/source/font/PhysicalFontFamily.cxx')
-rw-r--r-- | vcl/source/font/PhysicalFontFamily.cxx | 298 |
1 files changed, 298 insertions, 0 deletions
diff --git a/vcl/source/font/PhysicalFontFamily.cxx b/vcl/source/font/PhysicalFontFamily.cxx new file mode 100644 index 000000000000..f0f33071b1b3 --- /dev/null +++ b/vcl/source/font/PhysicalFontFamily.cxx @@ -0,0 +1,298 @@ +/* -*- 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 <sal/types.h> + +#include <rtl/ustring.hxx> + +#include "outdev.h" +#include "PhysicalFontFace.hxx" +#include "PhysicalFontCollection.hxx" + +#include "PhysicalFontFamily.hxx" + +void PhysicalFontFamily::CalcType( sal_uLong& rType, FontWeight& rWeight, FontWidth& rWidth, + FontFamily eFamily, const utl::FontNameAttr* pFontAttr ) +{ + if ( eFamily != FAMILY_DONTKNOW ) + { + if ( eFamily == FAMILY_SWISS ) + rType |= IMPL_FONT_ATTR_SANSSERIF; + else if ( eFamily == FAMILY_ROMAN ) + rType |= IMPL_FONT_ATTR_SERIF; + else if ( eFamily == FAMILY_SCRIPT ) + rType |= IMPL_FONT_ATTR_SCRIPT; + else if ( eFamily == FAMILY_MODERN ) + rType |= IMPL_FONT_ATTR_FIXED; + else if ( eFamily == FAMILY_DECORATIVE ) + rType |= IMPL_FONT_ATTR_DECORATIVE; + } + + if ( pFontAttr ) + { + rType |= pFontAttr->Type; + + if ( ((rWeight == WEIGHT_DONTKNOW) || (rWeight == WEIGHT_NORMAL)) && + (pFontAttr->Weight != WEIGHT_DONTKNOW) ) + rWeight = pFontAttr->Weight; + if ( ((rWidth == WIDTH_DONTKNOW) || (rWidth == WIDTH_NORMAL)) && + (pFontAttr->Width != WIDTH_DONTKNOW) ) + rWidth = pFontAttr->Width; + } +} + +static unsigned lcl_IsCJKFont( const OUString& rFontName ) +{ + // Test, if Fontname includes CJK characters --> In this case we + // mention that it is a CJK font + for(int i = 0; i < rFontName.getLength(); i++) + { + const sal_Unicode ch = rFontName[i]; + // japanese + if ( ((ch >= 0x3040) && (ch <= 0x30FF)) || + ((ch >= 0x3190) && (ch <= 0x319F)) ) + return IMPL_FONT_ATTR_CJK|IMPL_FONT_ATTR_CJK_JP; + + // korean + if ( ((ch >= 0xAC00) && (ch <= 0xD7AF)) || + ((ch >= 0x3130) && (ch <= 0x318F)) || + ((ch >= 0x1100) && (ch <= 0x11FF)) ) + return IMPL_FONT_ATTR_CJK|IMPL_FONT_ATTR_CJK_KR; + + // chinese + if ( ((ch >= 0x3400) && (ch <= 0x9FFF)) ) + return IMPL_FONT_ATTR_CJK|IMPL_FONT_ATTR_CJK_TC|IMPL_FONT_ATTR_CJK_SC; + + // cjk + if ( ((ch >= 0x3000) && (ch <= 0xD7AF)) || + ((ch >= 0xFF00) && (ch <= 0xFFEE)) ) + return IMPL_FONT_ATTR_CJK; + + } + + return 0; +} + + +PhysicalFontFamily::PhysicalFontFamily( const OUString& rSearchName ) +: mpFirst( NULL ), + maSearchName( rSearchName ), + mnTypeFaces( 0 ), + mnMatchType( 0 ), + meMatchWeight( WEIGHT_DONTKNOW ), + meMatchWidth( WIDTH_DONTKNOW ), + meFamily( FAMILY_DONTKNOW ), + mePitch( PITCH_DONTKNOW ), + mnMinQuality( -1 ) +{} + +PhysicalFontFamily::~PhysicalFontFamily() +{ + // release all physical font faces + while( mpFirst ) + { + PhysicalFontFace* pFace = mpFirst; + mpFirst = pFace->GetNextFace(); + delete pFace; + } +} + +bool PhysicalFontFamily::AddFontFace( PhysicalFontFace* pNewData ) +{ + pNewData->mpNext = NULL; + + if( !mpFirst ) + { + maName = pNewData->GetFamilyName(); + maMapNames = pNewData->maMapNames; + meFamily = pNewData->GetFamilyType(); + mePitch = pNewData->GetPitch(); + mnMinQuality = pNewData->mnQuality; + } + else + { + if( meFamily == FAMILY_DONTKNOW ) + meFamily = pNewData->GetFamilyType(); + if( mePitch == PITCH_DONTKNOW ) + mePitch = pNewData->GetPitch(); + if( mnMinQuality > pNewData->mnQuality ) + mnMinQuality = pNewData->mnQuality; + } + + // set attributes for attribute based font matching + if( pNewData->IsScalable() ) + mnTypeFaces |= FONT_FAMILY_SCALABLE; + + if( pNewData->IsSymbolFont() ) + mnTypeFaces |= FONT_FAMILY_SYMBOL; + else + mnTypeFaces |= FONT_FAMILY_NONESYMBOL; + + if( pNewData->GetWeight() != WEIGHT_DONTKNOW ) + { + if( pNewData->GetWeight() >= WEIGHT_SEMIBOLD ) + mnTypeFaces |= FONT_FAMILY_BOLD; + else if( pNewData->GetWeight() <= WEIGHT_SEMILIGHT ) + mnTypeFaces |= FONT_FAMILY_LIGHT; + else + mnTypeFaces |= FONT_FAMILY_NORMAL; + } + + if( pNewData->GetSlant() == ITALIC_NONE ) + mnTypeFaces |= FONT_FAMILY_NONEITALIC; + else if( (pNewData->GetSlant() == ITALIC_NORMAL) + || (pNewData->GetSlant() == ITALIC_OBLIQUE) ) + mnTypeFaces |= FONT_FAMILY_ITALIC; + + if( (meMatchWeight == WEIGHT_DONTKNOW) + || (meMatchWidth == WIDTH_DONTKNOW) + || (mnMatchType == 0) ) + { + // TODO: is it cheaper to calc matching attributes now or on demand? + // calc matching attributes if other entries are already initialized + + // Do lazy, quite expensive, not needed in start-up! + // const FontSubstConfiguration& rFontSubst = *FontSubstConfiguration::get(); + // InitMatchData( rFontSubst, maSearchName ); + // mbMatchData=true; // Somewhere else??? + } + + // reassign name (sharing saves memory) + if( pNewData->GetFamilyName() == GetFamilyName() ) + pNewData->SetFamilyName( GetFamilyName() ); + + // insert new physical font face into linked list + // TODO: get rid of linear search? + PhysicalFontFace* pData; + PhysicalFontFace** ppHere = &mpFirst; + for(; (pData=*ppHere) != NULL; ppHere=&pData->mpNext ) + { + sal_Int32 eComp = pNewData->CompareWithSize( *pData ); + if( eComp > 0 ) + continue; + if( eComp < 0 ) + break; + + // ignore duplicate if its quality is worse + if( pNewData->mnQuality < pData->mnQuality ) + return false; + + // keep the device font if its quality is good enough + if( (pNewData->mnQuality == pData->mnQuality) + && (pData->mbDevice || !pNewData->mbDevice) ) + return false; + + // replace existing font face with a better one + pNewData->mpNext = pData->mpNext; + *ppHere = pNewData; + delete pData; + return true; + } + + // insert into or append to list of physical font faces + pNewData->mpNext = pData; + *ppHere = pNewData; + return true; +} + +// get font attributes using the normalized font family name +void PhysicalFontFamily::InitMatchData( const utl::FontSubstConfiguration& rFontSubst, + const OUString& rSearchName ) +{ + OUString aShortName; + OUString aMatchFamilyName(maMatchFamilyName); + // get font attributes from the decorated font name + rFontSubst.getMapName( rSearchName, aShortName, aMatchFamilyName, + meMatchWeight, meMatchWidth, mnMatchType ); + maMatchFamilyName = aMatchFamilyName; + const utl::FontNameAttr* pFontAttr = rFontSubst.getSubstInfo( rSearchName ); + // eventually use the stripped name + if( !pFontAttr ) + if( aShortName != rSearchName ) + pFontAttr = rFontSubst.getSubstInfo( aShortName ); + CalcType( mnMatchType, meMatchWeight, meMatchWidth, meFamily, pFontAttr ); + mnMatchType |= lcl_IsCJKFont( maName ); +} + +PhysicalFontFace* PhysicalFontFamily::FindBestFontFace( const FontSelectPattern& rFSD ) const +{ + if( !mpFirst ) + return NULL; + if( !mpFirst->GetNextFace() ) + return mpFirst; + + // FontName+StyleName should map to FamilyName+StyleName + const OUString& rSearchName = rFSD.maTargetName; + OUString aTargetStyleName; + const OUString* pTargetStyleName = NULL; + if( (rSearchName.getLength() > maSearchName.getLength()) + && rSearchName.startsWith( maSearchName ) ) + { + aTargetStyleName = rSearchName.copy(maSearchName.getLength() + 1); + pTargetStyleName = &aTargetStyleName; + } + + // TODO: linear search improve! + PhysicalFontFace* pFontFace = mpFirst; + PhysicalFontFace* pBestFontFace = pFontFace; + FontMatchStatus aFontMatchStatus = {0,0,0, pTargetStyleName}; + for(; pFontFace; pFontFace = pFontFace->GetNextFace() ) + if( pFontFace->IsBetterMatch( rFSD, aFontMatchStatus ) ) + pBestFontFace = pFontFace; + + return pBestFontFace; +} + +// update device font list with unique font faces, with uniqueness +// meaning different font attributes, but not different fonts sizes +void PhysicalFontFamily::UpdateDevFontList( ImplGetDevFontList& rDevFontList ) const +{ + PhysicalFontFace* pPrevFace = NULL; + for( PhysicalFontFace* pFace = mpFirst; pFace; pFace = pFace->GetNextFace() ) + { + if( !pPrevFace || pFace->CompareIgnoreSize( *pPrevFace ) ) + rDevFontList.Add( pFace ); + pPrevFace = pFace; + } +} + +void PhysicalFontFamily::GetFontHeights( std::set<int>& rHeights ) const +{ + // add all available font heights + for( const PhysicalFontFace* pFace = mpFirst; pFace; pFace = pFace->GetNextFace() ) + rHeights.insert( pFace->GetHeight() ); +} + +void PhysicalFontFamily::UpdateCloneFontList( PhysicalFontCollection& rFontCollection, + bool bScalable, bool bEmbeddable ) const +{ + for( PhysicalFontFace* pFace = mpFirst; pFace; pFace = pFace->GetNextFace() ) + { + if( bScalable && !pFace->IsScalable() ) + continue; + if( bEmbeddable && !pFace->IsEmbeddable() && !pFace->IsSubsettable() ) + continue; + + PhysicalFontFace* pClonedFace = pFace->Clone(); + rFontCollection.Add( pClonedFace ); + } +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |