build fix: no comphelper/profilezone.hxx in this branch
[LibreOffice.git] / vcl / source / font / PhysicalFontFamily.cxx
blob5e28ab37a03f12a6ca6f0f69ff85ba2628b69ab5
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <rtl/ustring.hxx>
21 #include <unotools/fontdefs.hxx>
23 #include "outdev.h"
24 #include "PhysicalFontCollection.hxx"
26 void PhysicalFontFamily::CalcType( ImplFontAttrs& rType, FontWeight& rWeight, FontWidth& rWidth,
27 FontFamily eFamily, const utl::FontNameAttr* pFontAttr )
29 if ( eFamily != FAMILY_DONTKNOW )
31 if ( eFamily == FAMILY_SWISS )
32 rType |= ImplFontAttrs::SansSerif;
33 else if ( eFamily == FAMILY_ROMAN )
34 rType |= ImplFontAttrs::Serif;
35 else if ( eFamily == FAMILY_SCRIPT )
36 rType |= ImplFontAttrs::Script;
37 else if ( eFamily == FAMILY_MODERN )
38 rType |= ImplFontAttrs::Fixed;
39 else if ( eFamily == FAMILY_DECORATIVE )
40 rType |= ImplFontAttrs::Decorative;
43 if ( pFontAttr )
45 rType |= pFontAttr->Type;
47 if ( ((rWeight == WEIGHT_DONTKNOW) || (rWeight == WEIGHT_NORMAL)) &&
48 (pFontAttr->Weight != WEIGHT_DONTKNOW) )
49 rWeight = pFontAttr->Weight;
50 if ( ((rWidth == WIDTH_DONTKNOW) || (rWidth == WIDTH_NORMAL)) &&
51 (pFontAttr->Width != WIDTH_DONTKNOW) )
52 rWidth = pFontAttr->Width;
56 static ImplFontAttrs lcl_IsCJKFont( const OUString& rFontName )
58 // Test, if Fontname includes CJK characters --> In this case we
59 // mention that it is a CJK font
60 for(int i = 0; i < rFontName.getLength(); i++)
62 const sal_Unicode ch = rFontName[i];
63 // japanese
64 if ( ((ch >= 0x3040) && (ch <= 0x30FF)) ||
65 ((ch >= 0x3190) && (ch <= 0x319F)) )
66 return ImplFontAttrs::CJK|ImplFontAttrs::CJK_JP;
68 // korean
69 if ( ((ch >= 0xAC00) && (ch <= 0xD7AF)) ||
70 ((ch >= 0x3130) && (ch <= 0x318F)) ||
71 ((ch >= 0x1100) && (ch <= 0x11FF)) )
72 return ImplFontAttrs::CJK|ImplFontAttrs::CJK_KR;
74 // chinese
75 if ( ((ch >= 0x3400) && (ch <= 0x9FFF)) )
76 return ImplFontAttrs::CJK|ImplFontAttrs::CJK_TC|ImplFontAttrs::CJK_SC;
78 // cjk
79 if ( ((ch >= 0x3000) && (ch <= 0xD7AF)) ||
80 ((ch >= 0xFF00) && (ch <= 0xFFEE)) )
81 return ImplFontAttrs::CJK;
85 return ImplFontAttrs::None;
88 PhysicalFontFamily::PhysicalFontFamily( const OUString& rSearchName )
89 : maSearchName( rSearchName ),
90 mnTypeFaces( FontTypeFaces::NONE ),
91 meFamily( FAMILY_DONTKNOW ),
92 mePitch( PITCH_DONTKNOW ),
93 mnMinQuality( -1 ),
94 mnMatchType( ImplFontAttrs::None ),
95 meMatchWeight( WEIGHT_DONTKNOW ),
96 meMatchWidth( WIDTH_DONTKNOW )
99 PhysicalFontFamily::~PhysicalFontFamily()
101 // release all physical font faces
102 for( std::vector< PhysicalFontFace* >::iterator it=maFontFaces.begin(); it != maFontFaces.end(); )
104 delete *it;
105 it = maFontFaces.erase( it );
110 bool PhysicalFontFamily::AddFontFace( PhysicalFontFace* pNewFontFace )
112 if( maFontFaces.empty() )
114 maFamilyName = pNewFontFace->GetFamilyName();
115 maMapNames = pNewFontFace->GetMapNames();
116 meFamily = pNewFontFace->GetFamilyType();
117 mePitch = pNewFontFace->GetPitch();
118 mnMinQuality = pNewFontFace->GetQuality();
120 else
122 if( meFamily == FAMILY_DONTKNOW )
123 meFamily = pNewFontFace->GetFamilyType();
124 if( mePitch == PITCH_DONTKNOW )
125 mePitch = pNewFontFace->GetPitch();
126 if( mnMinQuality > pNewFontFace->GetQuality() )
127 mnMinQuality = pNewFontFace->GetQuality();
130 // set attributes for attribute based font matching
131 mnTypeFaces |= FontTypeFaces::Scalable;
133 if( pNewFontFace->IsSymbolFont() )
134 mnTypeFaces |= FontTypeFaces::Symbol;
135 else
136 mnTypeFaces |= FontTypeFaces::NoneSymbol;
138 if( pNewFontFace->GetWeight() != WEIGHT_DONTKNOW )
140 if( pNewFontFace->GetWeight() >= WEIGHT_SEMIBOLD )
141 mnTypeFaces |= FontTypeFaces::Bold;
142 else if( pNewFontFace->GetWeight() <= WEIGHT_SEMILIGHT )
143 mnTypeFaces |= FontTypeFaces::Light;
144 else
145 mnTypeFaces |= FontTypeFaces::Normal;
148 if( pNewFontFace->GetItalic() == ITALIC_NONE )
149 mnTypeFaces |= FontTypeFaces::NoneItalic;
150 else if( (pNewFontFace->GetItalic() == ITALIC_NORMAL)
151 || (pNewFontFace->GetItalic() == ITALIC_OBLIQUE) )
152 mnTypeFaces |= FontTypeFaces::Italic;
154 // reassign name (sharing saves memory)
155 if( pNewFontFace->GetFamilyName() == GetFamilyName() )
156 pNewFontFace->SetFamilyName( GetFamilyName() );
158 // add the new physical font face, replacing existing font face if necessary
159 // TODO: get rid of linear search?
160 auto it(maFontFaces.begin());
161 for (; it != maFontFaces.end(); ++it)
163 PhysicalFontFace* pFoundFontFace = *it;
164 sal_Int32 eComp = pNewFontFace->CompareWithSize( *pFoundFontFace );
165 if( eComp > 0 )
166 continue;
167 if( eComp < 0 )
168 break;
170 // ignore duplicate if its quality is worse
171 if( pNewFontFace->GetQuality() < pFoundFontFace->GetQuality() )
172 return false;
174 // keep the device font if its quality is good enough
175 if( pNewFontFace->GetQuality() == pFoundFontFace->GetQuality() )
176 return false;
178 // replace existing font face with a better one
179 delete pFoundFontFace;
180 *it = pNewFontFace; // insert at sort position
181 return true;
184 maFontFaces.insert(it, pNewFontFace); // insert at sort position
185 return true;
188 // get font attributes using the normalized font family name
189 void PhysicalFontFamily::InitMatchData( const utl::FontSubstConfiguration& rFontSubst,
190 const OUString& rSearchName )
192 OUString aShortName;
193 OUString aMatchFamilyName(maMatchFamilyName);
194 // get font attributes from the decorated font name
195 utl::FontSubstConfiguration::getMapName( rSearchName, aShortName, aMatchFamilyName,
196 meMatchWeight, meMatchWidth, mnMatchType );
197 maMatchFamilyName = aMatchFamilyName;
198 const utl::FontNameAttr* pFontAttr = rFontSubst.getSubstInfo( rSearchName );
199 // eventually use the stripped name
200 if( !pFontAttr )
201 if( aShortName != rSearchName )
202 pFontAttr = rFontSubst.getSubstInfo( aShortName );
203 CalcType( mnMatchType, meMatchWeight, meMatchWidth, meFamily, pFontAttr );
204 mnMatchType |= lcl_IsCJKFont( maFamilyName );
207 PhysicalFontFace* PhysicalFontFamily::FindBestFontFace( const FontSelectPattern& rFSD ) const
209 if( maFontFaces.empty() )
210 return nullptr;
211 if( maFontFaces.size() == 1)
212 return maFontFaces[0];
214 // FontName+StyleName should map to FamilyName+StyleName
215 const OUString& rSearchName = rFSD.maTargetName;
216 OUString aTargetStyleName;
217 const OUString* pTargetStyleName = nullptr;
218 if((rSearchName.getLength() > maSearchName.getLength())
219 && rSearchName.startsWith( maSearchName ) )
221 aTargetStyleName = rSearchName.copy(maSearchName.getLength() + 1);
222 pTargetStyleName = &aTargetStyleName;
225 // TODO: linear search improve!
226 PhysicalFontFace* pBestFontFace = maFontFaces[0];
227 FontMatchStatus aFontMatchStatus = {0,0,0, pTargetStyleName};
228 for( std::vector< PhysicalFontFace* >::const_iterator it=maFontFaces.begin(); it != maFontFaces.end(); ++it )
230 PhysicalFontFace* pFoundFontFace = *it;
231 if( pFoundFontFace->IsBetterMatch( rFSD, aFontMatchStatus ) )
232 pBestFontFace = pFoundFontFace;
235 return pBestFontFace;
238 // update device font list with unique font faces, with uniqueness
239 // meaning different font attributes, but not different fonts sizes
240 void PhysicalFontFamily::UpdateDevFontList( ImplDeviceFontList& rDevFontList ) const
242 PhysicalFontFace* pPrevFace = nullptr;
243 for(std::vector< PhysicalFontFace* >::const_iterator it=maFontFaces.begin(); it != maFontFaces.end(); ++it )
245 PhysicalFontFace* pFoundFontFace = *it;
246 if( !pPrevFace || pFoundFontFace->CompareIgnoreSize( *pPrevFace ) )
247 rDevFontList.Add( pFoundFontFace );
248 pPrevFace = pFoundFontFace;
252 void PhysicalFontFamily::GetFontHeights( std::set<int>& rHeights ) const
254 // add all available font heights
255 for( std::vector< PhysicalFontFace* >::const_iterator it=maFontFaces.begin(); it != maFontFaces.end(); ++it )
257 PhysicalFontFace *pFoundFontFace = *it;
258 rHeights.insert( pFoundFontFace->GetHeight() );
262 void PhysicalFontFamily::UpdateCloneFontList(PhysicalFontCollection& rFontCollection) const
264 OUString aFamilyName = GetEnglishSearchFontName( GetFamilyName() );
265 PhysicalFontFamily* pFamily(nullptr);
267 for( std::vector< PhysicalFontFace* >::const_iterator it=maFontFaces.begin(); it != maFontFaces.end(); ++it )
269 PhysicalFontFace *pFoundFontFace = *it;
271 if (!pFamily)
272 { // tdf#98989 lazy create as family without faces won't work
273 pFamily = rFontCollection.FindOrCreateFontFamily(aFamilyName);
275 assert(pFamily);
276 PhysicalFontFace* pClonedFace = pFoundFontFace->Clone();
278 #if OSL_DEBUG_LEVEL > 0
279 OUString aClonedFamilyName = GetEnglishSearchFontName( pClonedFace->GetFamilyName() );
280 assert( aClonedFamilyName == aFamilyName );
281 assert( rFontCollection.FindOrCreateFontFamily( aClonedFamilyName ) == pFamily );
282 #endif
284 if (! pFamily->AddFontFace( pClonedFace ) )
285 delete pClonedFace;
289 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */