summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorNorbert Thiebaud <nthiebaud@gmail.com>2014-03-20 00:22:26 -0500
committerNorbert Thiebaud <nthiebaud@gmail.com>2014-03-20 16:11:58 -0500
commit7260bcd68726739b5fe26b4d29a1de47e7b0f5a7 (patch)
tree360f470874da345bf0723cfd90684942824df739 /vcl
parent7154b092a716d4d0041a8a563294511ec9e5dbc6 (diff)
cosmetic: split PhysicalFontFamily/Collection out of outdev3.cxx
Change-Id: Iae8eb15413c0c069c14edd92c94ecb0113d9d371
Diffstat (limited to 'vcl')
-rw-r--r--vcl/Library_vcl.mk2
-rw-r--r--vcl/generic/fontmanager/fontsubst.cxx1
-rw-r--r--vcl/generic/glyphs/gcach_ftyp.cxx1
-rw-r--r--vcl/generic/print/genpspgraphics.cxx1
-rw-r--r--vcl/headless/svptext.cxx2
-rw-r--r--vcl/inc/PhysicalFontCollection.hxx90
-rw-r--r--vcl/inc/PhysicalFontFamily.hxx84
-rw-r--r--vcl/inc/generic/genpspgraphics.h1
-rw-r--r--vcl/inc/generic/glyphcache.hxx1
-rw-r--r--vcl/inc/magic.h23
-rw-r--r--vcl/inc/outdev.h56
-rw-r--r--vcl/inc/outfont.hxx65
-rw-r--r--vcl/inc/sallayout.hxx15
-rw-r--r--vcl/inc/unx/salgdi.h1
-rw-r--r--vcl/inc/win/salgdi.h1
-rw-r--r--vcl/quartz/ctfonts.cxx1
-rw-r--r--vcl/source/app/svmain.cxx1
-rw-r--r--vcl/source/font/PhysicalFontCollection.cxx1362
-rw-r--r--vcl/source/font/PhysicalFontFamily.cxx298
-rw-r--r--vcl/source/gdi/embeddedfontshelper.cxx20
-rw-r--r--vcl/source/gdi/outdev.cxx1
-rw-r--r--vcl/source/gdi/outdev3.cxx1472
-rw-r--r--vcl/source/gdi/print.cxx1
-rw-r--r--vcl/source/gdi/virdev.cxx1
-rw-r--r--vcl/source/window/window.cxx1
-rw-r--r--vcl/unx/generic/gdi/salgdi3.cxx1
-rw-r--r--vcl/win/source/gdi/salgdi3.cxx1
27 files changed, 1906 insertions, 1598 deletions
diff --git a/vcl/Library_vcl.mk b/vcl/Library_vcl.mk
index 80c6405964dd..e605343cb943 100644
--- a/vcl/Library_vcl.mk
+++ b/vcl/Library_vcl.mk
@@ -183,7 +183,9 @@ $(eval $(call gb_Library_add_exception_objects,vcl,\
vcl/source/filter/wmf/winwmf \
vcl/source/filter/wmf/wmf \
vcl/source/filter/wmf/wmfwr \
+ vcl/source/font/PhysicalFontCollection \
vcl/source/font/PhysicalFontFace \
+ vcl/source/font/PhysicalFontFamily \
vcl/source/fontsubset/cff \
vcl/source/fontsubset/fontsubset \
vcl/source/fontsubset/gsub \
diff --git a/vcl/generic/fontmanager/fontsubst.cxx b/vcl/generic/fontmanager/fontsubst.cxx
index f2f57f4a80bb..deeb7916004a 100644
--- a/vcl/generic/fontmanager/fontsubst.cxx
+++ b/vcl/generic/fontmanager/fontsubst.cxx
@@ -28,6 +28,7 @@
#include "salbmp.hxx"
#include "impfont.hxx"
#include "outdev.h"
+#include "PhysicalFontCollection.hxx"
#include "fontsubset.hxx"
#include "salprn.hxx"
diff --git a/vcl/generic/glyphs/gcach_ftyp.cxx b/vcl/generic/glyphs/gcach_ftyp.cxx
index ea6c966e1e57..eee46f4b68d3 100644
--- a/vcl/generic/glyphs/gcach_ftyp.cxx
+++ b/vcl/generic/glyphs/gcach_ftyp.cxx
@@ -41,6 +41,7 @@
#include "osl/thread.hxx"
#include "langboost.hxx"
+#include "PhysicalFontCollection.hxx"
#include "sft.hxx"
#include <ft2build.h>
diff --git a/vcl/generic/print/genpspgraphics.cxx b/vcl/generic/print/genpspgraphics.cxx
index 515dc0eee675..d111c28e1024 100644
--- a/vcl/generic/print/genpspgraphics.cxx
+++ b/vcl/generic/print/genpspgraphics.cxx
@@ -45,6 +45,7 @@
#include "impfont.hxx"
#include "langboost.hxx"
#include "outfont.hxx"
+#include "PhysicalFontCollection.hxx"
#include "PhysicalFontFace.hxx"
#include "salbmp.hxx"
#include "salprn.hxx"
diff --git a/vcl/headless/svptext.cxx b/vcl/headless/svptext.cxx
index 7fd3cd30e587..e53ac29514cd 100644
--- a/vcl/headless/svptext.cxx
+++ b/vcl/headless/svptext.cxx
@@ -38,6 +38,8 @@
#include "outfont.hxx"
#include "PhysicalFontFace.hxx"
+class PhysicalFontCollection;
+
using namespace basegfx;
using namespace basebmp;
diff --git a/vcl/inc/PhysicalFontCollection.hxx b/vcl/inc/PhysicalFontCollection.hxx
new file mode 100644
index 000000000000..9c0c7a19ada2
--- /dev/null
+++ b/vcl/inc/PhysicalFontCollection.hxx
@@ -0,0 +1,90 @@
+/* -*- 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 .
+ */
+#pragma once
+
+#include <vcl/dllapi.h>
+
+#include "outfont.hxx"
+#include "PhysicalFontFamily.hxx"
+
+// - PhysicalFontCollection -
+
+// TODO: merge with ImplFontCache
+// TODO: rename to LogicalFontManager
+
+class VCL_PLUGIN_PUBLIC PhysicalFontCollection
+{
+private:
+ friend class WinGlyphFallbackSubstititution;
+ mutable bool mbMatchData; // true if matching attributes are initialized
+ bool mbMapNames; // true if MapNames are available
+
+ typedef boost::unordered_map<const OUString, PhysicalFontFamily*,FontNameHash> PhysicalFontFamilies;
+ PhysicalFontFamilies maPhysicalFontFamilies;
+
+ ImplPreMatchFontSubstitution* mpPreMatchHook; // device specific prematch substitution
+ ImplGlyphFallbackFontSubstitution* mpFallbackHook; // device specific glyh fallback substitution
+
+public:
+ explicit PhysicalFontCollection();
+ virtual ~PhysicalFontCollection();
+
+ // fill the list with device fonts
+ void Add( PhysicalFontFace* );
+ void Clear();
+ int Count() const { return maPhysicalFontFamilies.size(); }
+
+ // find the device font
+ PhysicalFontFamily* FindFontFamily( const OUString& rFontName ) const;
+ PhysicalFontFamily* ImplFindByFont( FontSelectPattern& ) const;
+ PhysicalFontFamily* ImplFindBySearchName( const OUString& ) const;
+
+ // suggest fonts for glyph fallback
+ PhysicalFontFamily* GetGlyphFallbackFont( FontSelectPattern&,
+ OUString& rMissingCodes, int nFallbackLevel ) const;
+
+ // prepare platform specific font substitutions
+ void SetPreMatchHook( ImplPreMatchFontSubstitution* );
+ void SetFallbackHook( ImplGlyphFallbackFontSubstitution* );
+
+ // misc utilities
+ PhysicalFontCollection* Clone( bool bScalable, bool bEmbeddable ) const;
+ ImplGetDevFontList* GetDevFontList() const;
+ ImplGetDevSizeList* GetDevSizeList( const OUString& rFontName ) const;
+
+ PhysicalFontFamily* ImplFindByTokenNames(const OUString& rTokenStr) const;
+
+protected:
+ void InitMatchData() const;
+ bool AreMapNamesAvailable() const { return mbMapNames; }
+
+ PhysicalFontFamily* ImplFindByAliasName(const OUString& rSearchName,
+ const OUString& rShortName) const;
+ PhysicalFontFamily* ImplFindBySubstFontAttr( const utl::FontNameAttr& ) const;
+ PhysicalFontFamily* ImplFindByAttributes(sal_uLong nSearchType, FontWeight, FontWidth,
+ FontItalic, const OUString& rSearchFamily) const;
+ PhysicalFontFamily* FindDefaultFont() const;
+
+private:
+ void InitGenericGlyphFallback() const;
+ mutable PhysicalFontFamily** mpFallbackList;
+ mutable int mnFallbackCount;
+};
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/PhysicalFontFamily.hxx b/vcl/inc/PhysicalFontFamily.hxx
new file mode 100644
index 000000000000..b1f56dece2db
--- /dev/null
+++ b/vcl/inc/PhysicalFontFamily.hxx
@@ -0,0 +1,84 @@
+/* -*- 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 .
+ */
+#pragma once
+
+#include <set>
+
+#include <unotools/fontcfg.hxx>
+
+#include "PhysicalFontFace.hxx"
+#include "PhysicalFontFamily.hxx"
+
+class PhysicalFontFace;
+class PhysicalFontCollection;
+
+// flags for mnMatchType member
+#define FONT_FAMILY_SCALABLE (1<<0)
+#define FONT_FAMILY_SYMBOL (1<<1)
+#define FONT_FAMILY_NONESYMBOL (1<<2)
+#define FONT_FAMILY_LIGHT (1<<4)
+#define FONT_FAMILY_BOLD (1<<5)
+#define FONT_FAMILY_NORMAL (1<<6)
+#define FONT_FAMILY_NONEITALIC (1<<8)
+#define FONT_FAMILY_ITALIC (1<<9)
+
+class PhysicalFontFamily
+{
+public:
+ PhysicalFontFamily( const OUString& rSearchName );
+ ~PhysicalFontFamily();
+
+ const OUString& GetFamilyName() const { return maName; }
+ const OUString& GetSearchName() const { return maSearchName; }
+ const OUString& GetAliasNames() const { return maMapNames; }
+ const OUString& GetMatchFamilyName() const { return maMatchFamilyName; }
+ sal_uLong GetMatchType() const { return mnMatchType ; }
+ FontWeight GetMatchWeight() const { return meMatchWeight ; }
+ FontWidth GetMatchWidth() const { return meMatchWidth ; }
+ bool IsScalable() const { return mpFirst->IsScalable(); }
+ int GetMinQuality() const { return mnMinQuality; }
+ int GetTypeFaces() const { return mnTypeFaces; }
+ bool AddFontFace( PhysicalFontFace* );
+ void InitMatchData( const utl::FontSubstConfiguration&,
+ const OUString& rSearchName );
+ PhysicalFontFace* FindBestFontFace( const FontSelectPattern& rFSD ) const;
+
+ void GetFontHeights( std::set<int>& rHeights ) const;
+ void UpdateDevFontList( ImplGetDevFontList& ) const;
+ void UpdateCloneFontList( PhysicalFontCollection&,
+ bool bScalable, bool bEmbeddable ) const;
+
+static void CalcType( sal_uLong& rType, FontWeight& rWeight, FontWidth& rWidth,
+ FontFamily eFamily, const utl::FontNameAttr* pFontAttr );
+
+private:
+ PhysicalFontFace* mpFirst; // linked list of physical font faces
+ OUString maName; // Fontname (original font family name)
+ OUString maSearchName; // normalized font family name
+ OUString maMapNames; // fontname aliases
+ int mnTypeFaces; // Typeface Flags
+ sal_uLong mnMatchType; // MATCH - Type
+ OUString maMatchFamilyName; // MATCH - FamilyName
+ FontWeight meMatchWeight; // MATCH - Weight
+ FontWidth meMatchWidth; // MATCH - Width
+ FontFamily meFamily;
+ FontPitch mePitch;
+ int mnMinQuality; // quality of the worst font face
+};
+
diff --git a/vcl/inc/generic/genpspgraphics.h b/vcl/inc/generic/genpspgraphics.h
index ea7d381545fc..3d1bbc7178fc 100644
--- a/vcl/inc/generic/genpspgraphics.h
+++ b/vcl/inc/generic/genpspgraphics.h
@@ -29,6 +29,7 @@
#include "vclpluginapi.h"
class PhysicalFontFace;
+class PhysicalFontCollection;
namespace psp { struct JobData; class PrinterGfx; }
diff --git a/vcl/inc/generic/glyphcache.hxx b/vcl/inc/generic/glyphcache.hxx
index 47188e9370c5..28770f784ab2 100644
--- a/vcl/inc/generic/glyphcache.hxx
+++ b/vcl/inc/generic/glyphcache.hxx
@@ -30,6 +30,7 @@ class GlyphCachePeer;
class ServerFontLayoutEngine;
class ServerFontLayout;
class ImplFontOptions;
+class PhysicalFontCollection;
#include <tools/gen.hxx>
#include <basebmp/bitmapdevice.hxx>
diff --git a/vcl/inc/magic.h b/vcl/inc/magic.h
new file mode 100644
index 000000000000..7da1d09b9b50
--- /dev/null
+++ b/vcl/inc/magic.h
@@ -0,0 +1,23 @@
+/* -*- 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 .
+ */
+#pragma once
+
+#define MAX_FALLBACK 16
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/outdev.h b/vcl/inc/outdev.h
index 9baba35dc988..a8f4037a0dd5 100644
--- a/vcl/inc/outdev.h
+++ b/vcl/inc/outdev.h
@@ -24,6 +24,8 @@
#include <set>
#include <vector>
+#include <tools/gen.hxx>
+
#include "outfont.hxx"
#include "PhysicalFontFace.hxx"
@@ -32,56 +34,7 @@ class Font;
class VirtualDevice;
class ImplGetDevFontList;
class GetDevSizeList;
-
-// flags for mnMatchType member
-#define IMPL_DEVFONT_SCALABLE ((sal_uIntPtr)0x00000001)
-#define IMPL_DEVFONT_SYMBOL ((sal_uIntPtr)0x00000002)
-#define IMPL_DEVFONT_NONESYMBOL ((sal_uIntPtr)0x00000004)
-#define IMPL_DEVFONT_LIGHT ((sal_uIntPtr)0x00000010)
-#define IMPL_DEVFONT_BOLD ((sal_uIntPtr)0x00000020)
-#define IMPL_DEVFONT_NORMAL ((sal_uIntPtr)0x00000040)
-#define IMPL_DEVFONT_NONEITALIC ((sal_uIntPtr)0x00000100)
-#define IMPL_DEVFONT_ITALIC ((sal_uIntPtr)0x00000200)
-
-
-class PhysicalFontFamily
-{
-public:
- PhysicalFontFamily( const OUString& rSearchName );
- ~PhysicalFontFamily();
-
- const OUString& GetFamilyName() const { return maName; }
- const OUString& GetSearchName() const { return maSearchName; }
- const OUString& GetAliasNames() const { return maMapNames; }
- bool IsScalable() const { return mpFirst->IsScalable(); }
- int GetMinQuality() const { return mnMinQuality; }
-
- bool AddFontFace( PhysicalFontFace* );
- void InitMatchData( const utl::FontSubstConfiguration&,
- const OUString& rSearchName );
- PhysicalFontFace* FindBestFontFace( const FontSelectPattern& rFSD ) const;
-
- void GetFontHeights( std::set<int>& rHeights ) const;
- void UpdateDevFontList( ImplGetDevFontList& ) const;
- void UpdateCloneFontList( PhysicalFontCollection&,
- bool bScalable, bool bEmbeddable ) const;
-
-private:
-friend class PhysicalFontCollection; // TODO: remove soon
- PhysicalFontFace* mpFirst; // linked list of physical font faces
- OUString maName; // Fontname (original font family name)
- OUString maSearchName; // normalized font family name
- OUString maMapNames; // fontname aliases
- sal_uIntPtr mnTypeFaces; // Typeface Flags
- sal_uIntPtr mnMatchType; // MATCH - Type
- OUString maMatchFamilyName; // MATCH - FamilyName
- FontWeight meMatchWeight; // MATCH - Weight
- FontWidth meMatchWidth; // MATCH - Width
- FontFamily meFamily;
- FontPitch mePitch;
- int mnMinQuality; // quality of the worst font face
-};
-
+class PhysicalFontCollection;
// an ImplGetDevFontList is created by an PhysicalFontCollection
// it becomes invalid when original PhysicalFontCollection is modified
class ImplGetDevFontList
@@ -218,6 +171,9 @@ struct ImplOutDevData
basegfx::B2DHomMatrix* mpInverseViewTransform;
};
+void ImplFontSubstitute( OUString& rFontName );
+
+
#endif // INCLUDED_VCL_INC_OUTDEV_H
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/outfont.hxx b/vcl/inc/outfont.hxx
index 12adb7cc7837..798f2611dcdc 100644
--- a/vcl/inc/outfont.hxx
+++ b/vcl/inc/outfont.hxx
@@ -161,71 +161,6 @@ public: // TODO: change to private
};
-// - PhysicalFontCollection -
-
-// TODO: merge with ImplFontCache
-// TODO: rename to LogicalFontManager
-
-class VCL_PLUGIN_PUBLIC PhysicalFontCollection
-{
-private:
- friend class WinGlyphFallbackSubstititution;
- mutable bool mbMatchData; // true if matching attributes are initialized
- bool mbMapNames; // true if MapNames are available
-
- typedef boost::unordered_map<const OUString, PhysicalFontFamily*,FontNameHash> PhysicalFontFamilies;
- PhysicalFontFamilies maPhysicalFontFamilies;
-
- ImplPreMatchFontSubstitution* mpPreMatchHook; // device specific prematch substitution
- ImplGlyphFallbackFontSubstitution* mpFallbackHook; // device specific glyh fallback substitution
-
-public:
- explicit PhysicalFontCollection();
- virtual ~PhysicalFontCollection();
-
- // fill the list with device fonts
- void Add( PhysicalFontFace* );
- void Clear();
- int Count() const { return maPhysicalFontFamilies.size(); }
-
- // find the device font
- PhysicalFontFamily* FindFontFamily( const OUString& rFontName ) const;
- PhysicalFontFamily* ImplFindByFont( FontSelectPattern& ) const;
- PhysicalFontFamily* ImplFindBySearchName( const OUString& ) const;
-
- // suggest fonts for glyph fallback
- PhysicalFontFamily* GetGlyphFallbackFont( FontSelectPattern&,
- OUString& rMissingCodes, int nFallbackLevel ) const;
-
- // prepare platform specific font substitutions
- void SetPreMatchHook( ImplPreMatchFontSubstitution* );
- void SetFallbackHook( ImplGlyphFallbackFontSubstitution* );
-
- // misc utilities
- PhysicalFontCollection* Clone( bool bScalable, bool bEmbeddable ) const;
- ImplGetDevFontList* GetDevFontList() const;
- ImplGetDevSizeList* GetDevSizeList( const OUString& rFontName ) const;
-
- PhysicalFontFamily* ImplFindByTokenNames(const OUString& rTokenStr) const;
-
-protected:
- void InitMatchData() const;
- bool AreMapNamesAvailable() const { return mbMapNames; }
-
- PhysicalFontFamily* ImplFindByAliasName(const OUString& rSearchName,
- const OUString& rShortName) const;
- PhysicalFontFamily* ImplFindBySubstFontAttr( const utl::FontNameAttr& ) const;
- PhysicalFontFamily* ImplFindByAttributes(sal_uLong nSearchType, FontWeight, FontWidth,
- FontItalic, const OUString& rSearchFamily) const;
- PhysicalFontFamily* FindDefaultFont() const;
-
-private:
- void InitGenericGlyphFallback() const;
- mutable PhysicalFontFamily** mpFallbackList;
- mutable int mnFallbackCount;
-};
-
-
// - ImplFontMetricData -
diff --git a/vcl/inc/sallayout.hxx b/vcl/inc/sallayout.hxx
index f3727bab61b3..57e7480369fd 100644
--- a/vcl/inc/sallayout.hxx
+++ b/vcl/inc/sallayout.hxx
@@ -21,28 +21,25 @@
#define INCLUDED_VCL_INC_SALLAYOUT_HXX
#include <iostream>
+#include <list>
+#include <vector>
-#include <tools/gen.hxx>
#include <basegfx/polygon/b2dpolypolygon.hxx>
#include <i18nlangtag/languagetag.hxx>
+#include <tools/gen.hxx>
+#include <vcl/dllapi.h>
+#include <vcl/vclenum.hxx> // for typedef sal_UCS4
#ifndef _TOOLS_LANG_HXX
typedef unsigned short LanguageType;
#endif
-#include <vector>
-#include <list>
-#include <vcl/dllapi.h>
-
-// for typedef sal_UCS4
-#include <vcl/vclenum.hxx>
+#include "magic.h"
#include "salglyphid.hxx"
class SalGraphics;
class PhysicalFontFace;
-#define MAX_FALLBACK 16
-
// Layout options
#define SAL_LAYOUT_BIDI_RTL 0x0001
#define SAL_LAYOUT_BIDI_STRONG 0x0002
diff --git a/vcl/inc/unx/salgdi.h b/vcl/inc/unx/salgdi.h
index da91204b6b2a..03e7f50662a5 100644
--- a/vcl/inc/unx/salgdi.h
+++ b/vcl/inc/unx/salgdi.h
@@ -46,6 +46,7 @@ class PspSalInfoPrinter;
class ServerFont;
class ImplLayoutArgs;
class ServerFontLayout;
+class PhysicalFontCollection;
class PhysicalFontFace;
namespace basegfx {
diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h
index c649cc3cc9ab..dac4d6e6565d 100644
--- a/vcl/inc/win/salgdi.h
+++ b/vcl/inc/win/salgdi.h
@@ -39,6 +39,7 @@
class FontSelectPattern;
class ImplWinFontEntry;
class ImplFontAttrCache;
+class PhysicalFontCollection;
#define RGB_TO_PALRGB(nRGB) ((nRGB)|0x02000000)
#define PALRGB_TO_RGB(nPalRGB) ((nPalRGB)&0x00ffffff)
diff --git a/vcl/quartz/ctfonts.cxx b/vcl/quartz/ctfonts.cxx
index 2506d31c973d..ce44ca8e1e8e 100644
--- a/vcl/quartz/ctfonts.cxx
+++ b/vcl/quartz/ctfonts.cxx
@@ -21,6 +21,7 @@
#include "impfont.hxx"
#include "outfont.hxx"
+#include "PhysicalFontCollection.hxx"
#include "sallayout.hxx"
#ifdef MACOSX
diff --git a/vcl/source/app/svmain.cxx b/vcl/source/app/svmain.cxx
index 6d572b416dbf..3047488f4748 100644
--- a/vcl/source/app/svmain.cxx
+++ b/vcl/source/app/svmain.cxx
@@ -58,6 +58,7 @@
#include "idlemgr.hxx"
#include "outdev.h"
#include "outfont.hxx"
+#include "PhysicalFontCollection.hxx"
#include "print.h"
#include "salsys.hxx"
#include "saltimer.hxx"
diff --git a/vcl/source/font/PhysicalFontCollection.cxx b/vcl/source/font/PhysicalFontCollection.cxx
new file mode 100644
index 000000000000..6dcecc5d2766
--- /dev/null
+++ b/vcl/source/font/PhysicalFontCollection.cxx
@@ -0,0 +1,1362 @@
+/* -*- 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 <vector>
+
+#include <i18nlangtag/mslangid.hxx>
+
+#include <config_graphite.h>
+#if ENABLE_GRAPHITE
+#include "graphite_features.hxx"
+#endif
+
+#include "magic.h"
+#include "outdev.h"
+#include "outfont.hxx"
+#include "PhysicalFontFace.hxx"
+
+#include "PhysicalFontCollection.hxx"
+
+static OUString lcl_stripCharSetFromName(const OUString& _aName)
+{
+ // I worry that someone will have a font which *does* have
+ // e.g. "Greek" legitimately at the end of its name :-(
+ const char*suffixes[] = { " baltic",
+ " ce",
+ " cyr",
+ " greek",
+ " tur",
+ " (arabic)",
+ " (hebrew)",
+ " (thai)",
+ " (vietnamese)"
+ };
+
+ OUString aName = _aName;
+ // These can be crazily piled up, e.g. Times New Roman CYR Greek
+ bool bFinished = false;
+ while (!bFinished)
+ {
+ bFinished = true;
+ for (size_t i = 0; i < SAL_N_ELEMENTS(suffixes); ++i)
+ {
+ size_t nLen = strlen(suffixes[i]);
+ if (aName.endsWithIgnoreAsciiCaseAsciiL(suffixes[i], nLen))
+ {
+ bFinished = false;
+ aName = aName.copy(0, aName.getLength() - nLen);
+ }
+ }
+ }
+ return aName;
+}
+
+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;
+}
+
+
+PhysicalFontCollection::PhysicalFontCollection()
+ : mbMatchData( false )
+ , mbMapNames( false )
+ , mpPreMatchHook( NULL )
+ , mpFallbackHook( NULL )
+ , mpFallbackList( NULL )
+ , mnFallbackCount( -1 )
+{}
+
+PhysicalFontCollection::~PhysicalFontCollection()
+{
+ Clear();
+}
+
+void PhysicalFontCollection::SetPreMatchHook( ImplPreMatchFontSubstitution* pHook )
+{
+ mpPreMatchHook = pHook;
+}
+
+void PhysicalFontCollection::SetFallbackHook( ImplGlyphFallbackFontSubstitution* pHook )
+{
+ mpFallbackHook = pHook;
+}
+
+void PhysicalFontCollection::Clear()
+{
+ // remove fallback lists
+ delete[] mpFallbackList;
+ mpFallbackList = NULL;
+ mnFallbackCount = -1;
+
+ // clear all entries in the device font list
+ PhysicalFontFamilies::iterator it = maPhysicalFontFamilies.begin();
+ for(; it != maPhysicalFontFamilies.end(); ++it )
+ {
+ PhysicalFontFamily* pEntry = (*it).second;
+ delete pEntry;
+ }
+
+ maPhysicalFontFamilies.clear();
+
+ // match data must be recalculated too
+ mbMatchData = false;
+}
+
+void PhysicalFontCollection::InitGenericGlyphFallback( void ) const
+{
+ // normalized family names of fonts suited for glyph fallback
+ // if a font is available related fonts can be ignored
+ // TODO: implement dynamic lists
+ static const char* aGlyphFallbackList[] = {
+ // empty strings separate the names of unrelated fonts
+ "eudc", "",
+ "arialunicodems", "cyberbit", "code2000", "",
+ "andalesansui", "",
+ "starsymbol", "opensymbol", "",
+ "msmincho", "fzmingti", "fzheiti", "ipamincho", "sazanamimincho", "kochimincho", "",
+ "sunbatang", "sundotum", "baekmukdotum", "gulim", "batang", "dotum", "",
+ "hgmincholightj", "msunglightsc", "msunglighttc", "hymyeongjolightk", "",
+ "tahoma", "dejavusans", "timesnewroman", "liberationsans", "",
+ "shree", "mangal", "",
+ "raavi", "shruti", "tunga", "",
+ "latha", "gautami", "kartika", "vrinda", "",
+ "shayyalmt", "naskmt", "scheherazade", "",
+ "david", "nachlieli", "lucidagrande", "",
+ "norasi", "angsanaupc", "",
+ "khmerossystem", "",
+ "muktinarrow", "",
+ "phetsarathot", "",
+ "padauk", "pinlonmyanmar", "",
+ "iskoolapota", "lklug", "",
+ 0
+ };
+
+ bool bHasEudc = false;
+ int nMaxLevel = 0;
+ int nBestQuality = 0;
+ PhysicalFontFamily** pFallbackList = NULL;
+
+ for( const char** ppNames = &aGlyphFallbackList[0];; ++ppNames )
+ {
+ // advance to next sub-list when end-of-sublist marker
+ if( !**ppNames ) // #i46456# check for empty string, i.e., deref string itself not only ptr to it
+ {
+ if( nBestQuality > 0 )
+ if( ++nMaxLevel >= MAX_FALLBACK )
+ break;
+
+ if( !ppNames[1] )
+ break;
+
+ nBestQuality = 0;
+ continue;
+ }
+
+ // test if the glyph fallback candidate font is available and scalable
+ OUString aTokenName( *ppNames, strlen(*ppNames), RTL_TEXTENCODING_UTF8 );
+ PhysicalFontFamily* pFallbackFont = FindFontFamily( aTokenName );
+
+ if( !pFallbackFont )
+ continue;
+
+ if( !pFallbackFont->IsScalable() )
+ continue;
+
+ // keep the best font of the glyph fallback sub-list
+ if( nBestQuality < pFallbackFont->GetMinQuality() )
+ {
+ nBestQuality = pFallbackFont->GetMinQuality();
+ // store available glyph fallback fonts
+ if( !pFallbackList )
+ pFallbackList = new PhysicalFontFamily*[ MAX_FALLBACK ];
+
+ pFallbackList[ nMaxLevel ] = pFallbackFont;
+ if( !bHasEudc && !nMaxLevel )
+ bHasEudc = !strncmp( *ppNames, "eudc", 5 );
+ }
+ }
+
+#ifdef SAL_FONTENUM_STABLE_ON_PLATFORM // #i113472#
+ // sort the list of fonts for glyph fallback by quality (highest first)
+ // #i33947# keep the EUDC font at the front of the list
+ // an insertion sort is good enough for this short list
+ const int nSortStart = bHasEudc ? 1 : 0;
+ for( int i = nSortStart+1, j; i < nMaxLevel; ++i )
+ {
+ PhysicalFontFamily* pTestFont = pFallbackList[ i ];
+ int nTestQuality = pTestFont->GetMinQuality();
+
+ for( j = i; --j >= nSortStart; )
+ {
+ if( nTestQuality > pFallbackList[j]->GetMinQuality() )
+ pFallbackList[ j+1 ] = pFallbackList[ j ];
+ else
+ break;
+ }
+ pFallbackList[ j+1 ] = pTestFont;
+ }
+#endif
+
+ mnFallbackCount = nMaxLevel;
+ mpFallbackList = pFallbackList;
+}
+
+PhysicalFontFamily* PhysicalFontCollection::GetGlyphFallbackFont( FontSelectPattern& rFontSelData,
+ OUString& rMissingCodes,
+ int nFallbackLevel ) const
+{
+ PhysicalFontFamily* pFallbackData = NULL;
+
+ // find a matching font candidate for platform specific glyph fallback
+ if( mpFallbackHook )
+ {
+ // check cache for the first matching entry
+ // to avoid calling the expensive fallback hook (#i83491#)
+ sal_UCS4 cChar = 0;
+ bool bCached = true;
+ sal_Int32 nStrIndex = 0;
+ while( nStrIndex < rMissingCodes.getLength() )
+ {
+ cChar = rMissingCodes.iterateCodePoints( &nStrIndex );
+ bCached = rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &rFontSelData.maSearchName );
+
+ // ignore entries which don't have a fallback
+ if( !bCached || !rFontSelData.maSearchName.isEmpty() )
+ break;
+ }
+
+ if( bCached )
+ {
+ // there is a matching fallback in the cache
+ // so update rMissingCodes with codepoints not yet resolved by this fallback
+ int nRemainingLength = 0;
+ sal_UCS4* pRemainingCodes = (sal_UCS4*)alloca( rMissingCodes.getLength() * sizeof(sal_UCS4) );
+ OUString aFontName;
+
+ while( nStrIndex < rMissingCodes.getLength() )
+ {
+ cChar = rMissingCodes.iterateCodePoints( &nStrIndex );
+ bCached = rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &aFontName );
+ if( !bCached || (rFontSelData.maSearchName != aFontName) )
+ pRemainingCodes[ nRemainingLength++ ] = cChar;
+ }
+ rMissingCodes = OUString( pRemainingCodes, nRemainingLength );
+ }
+ else
+ {
+ OUString aOldMissingCodes = rMissingCodes;
+
+ // call the hook to query the best matching glyph fallback font
+ if( mpFallbackHook->FindFontSubstitute( rFontSelData, rMissingCodes ) )
+ // apply outdev3.cxx specific fontname normalization
+ GetEnglishSearchFontName( rFontSelData.maSearchName );
+ else
+ rFontSelData.maSearchName = "";
+
+ // See fdo#32665 for an example. FreeSerif that has glyphs in normal
+ // font, but not in the italic or bold version
+ bool bSubSetOfFontRequiresPropertyFaking = rFontSelData.mbEmbolden || rFontSelData.maItalicMatrix != ItalicMatrix();
+
+ // Cache the result even if there was no match, unless its from part of a font for which the properties need
+ // to be faked. We need to rework this cache to take into account that fontconfig can return different fonts
+ // for different input sizes, weights, etc. Basically the cache is way to naive
+ if (!bSubSetOfFontRequiresPropertyFaking)
+ {
+ for(;;)
+ {
+ if( !rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &rFontSelData.maSearchName ) )
+ rFontSelData.mpFontEntry->AddFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName );
+ if( nStrIndex >= aOldMissingCodes.getLength() )
+ break;
+ cChar = aOldMissingCodes.iterateCodePoints( &nStrIndex );
+ }
+ if( !rFontSelData.maSearchName.isEmpty() )
+ {
+ // remove cache entries that were still not resolved
+ for( nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); )
+ {
+ cChar = rMissingCodes.iterateCodePoints( &nStrIndex );
+ rFontSelData.mpFontEntry->IgnoreFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName );
+ }
+ }
+ }
+ }
+
+ // find the matching device font
+ if( !rFontSelData.maSearchName.isEmpty() )
+ pFallbackData = FindFontFamily( rFontSelData.maSearchName );
+ }
+
+ // else find a matching font candidate for generic glyph fallback
+ if( !pFallbackData )
+ {
+ // initialize font candidates for generic glyph fallback if needed
+ if( mnFallbackCount < 0 )
+ InitGenericGlyphFallback();
+
+ // TODO: adjust nFallbackLevel by number of levels resolved by the fallback hook
+ if( nFallbackLevel < mnFallbackCount )
+ pFallbackData = mpFallbackList[ nFallbackLevel ];
+ }
+
+ return pFallbackData;
+}
+
+void PhysicalFontCollection::Add( PhysicalFontFace* pNewData )
+{
+ OUString aSearchName = pNewData->GetFamilyName();
+ GetEnglishSearchFontName( aSearchName );
+
+ PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.find( aSearchName );
+ PhysicalFontFamily* pFoundData = NULL;
+
+ if( it != maPhysicalFontFamilies.end() )
+ pFoundData = (*it).second;
+
+ if( !pFoundData )
+ {
+ pFoundData = new PhysicalFontFamily( aSearchName );
+ maPhysicalFontFamilies[ aSearchName ] = pFoundData;
+ }
+
+ bool bKeepNewData = pFoundData->AddFontFace( pNewData );
+
+ if( !bKeepNewData )
+ delete pNewData;
+}
+
+// find the font from the normalized font family name
+PhysicalFontFamily* PhysicalFontCollection::ImplFindBySearchName( const OUString& rSearchName ) const
+{
+#ifdef DEBUG
+ OUString aTempName = rSearchName;
+ GetEnglishSearchFontName( aTempName );
+ DBG_ASSERT( aTempName == rSearchName, "PhysicalFontCollection::ImplFindBySearchName() called with non-normalized name" );
+#endif
+
+ PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.find( rSearchName );
+ if( it == maPhysicalFontFamilies.end() )
+ return NULL;
+
+ PhysicalFontFamily* pFoundData = (*it).second;
+ return pFoundData;
+}
+
+PhysicalFontFamily* PhysicalFontCollection::ImplFindByAliasName(const OUString& rSearchName,
+ const OUString& rShortName) const
+{
+ // short circuit for impossible font name alias
+ if (rSearchName.isEmpty())
+ return NULL;
+
+ // short circuit if no alias names are available
+ if (!mbMapNames)
+ return NULL;
+
+ // use the font's alias names to find the font
+ // TODO: get rid of linear search
+ PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.begin();
+ while( it != maPhysicalFontFamilies.end() )
+ {
+ PhysicalFontFamily* pData = (*it).second;
+ if( pData->GetAliasNames().isEmpty() )
+ continue;
+
+ // if one alias name matches we found a matching font
+ OUString aTempName;
+ sal_Int32 nIndex = 0;
+
+ do
+ {
+ aTempName = GetNextFontToken( pData->GetAliasNames(), nIndex );
+ // Test, if the Font name match with one of the mapping names
+ if ( (aTempName == rSearchName) || (aTempName == rShortName) )
+ return pData;
+ }
+ while ( nIndex != -1 );
+ }
+
+ return NULL;
+}
+
+PhysicalFontFamily* PhysicalFontCollection::FindFontFamily( const OUString& rFontName ) const
+{
+ // normalize the font family name and
+ OUString aName = rFontName;
+ GetEnglishSearchFontName( aName );
+
+ PhysicalFontFamily* pFound = ImplFindBySearchName( aName );
+ return pFound;
+}
+
+PhysicalFontFamily* PhysicalFontCollection::ImplFindByTokenNames(const OUString& rTokenStr) const
+{
+ PhysicalFontFamily* pFoundData = NULL;
+
+ // use normalized font name tokens to find the font
+ for( sal_Int32 nTokenPos = 0; nTokenPos != -1; )
+ {
+ OUString aSearchName = GetNextFontToken( rTokenStr, nTokenPos );
+ if( aSearchName.isEmpty() )
+ continue;
+
+ GetEnglishSearchFontName( aSearchName );
+ pFoundData = ImplFindBySearchName( aSearchName );
+
+ if( pFoundData )
+ break;
+ }
+
+ return pFoundData;
+}
+
+PhysicalFontFamily* PhysicalFontCollection::ImplFindBySubstFontAttr( const utl::FontNameAttr& rFontAttr ) const
+{
+ PhysicalFontFamily* pFoundData = NULL;
+
+ // use the font substitutions suggested by the FontNameAttr to find the font
+ ::std::vector< OUString >::const_iterator it = rFontAttr.Substitutions.begin();
+ for(; it != rFontAttr.Substitutions.end(); ++it )
+ {
+ OUString aSearchName( *it );
+ GetEnglishSearchFontName( aSearchName );
+
+ pFoundData = ImplFindBySearchName( aSearchName );
+ if( pFoundData )
+ return pFoundData;
+ }
+
+ // use known attributes from the configuration to find a matching substitute
+ const sal_uLong nSearchType = rFontAttr.Type;
+ if( nSearchType != 0 )
+ {
+ const FontWeight eSearchWeight = rFontAttr.Weight;
+ const FontWidth eSearchWidth = rFontAttr.Width;
+ const FontItalic eSearchSlant = ITALIC_DONTKNOW;
+ const OUString aSearchName;
+
+ pFoundData = ImplFindByAttributes( nSearchType,
+ eSearchWeight, eSearchWidth, eSearchSlant, aSearchName );
+
+ if( pFoundData )
+ return pFoundData;
+ }
+
+ return NULL;
+}
+
+void PhysicalFontCollection::InitMatchData() const
+{
+ // short circuit if already done
+ if( mbMatchData )
+ return;
+ mbMatchData = true;
+
+ // calculate MatchData for all entries
+ const utl::FontSubstConfiguration& rFontSubst = utl::FontSubstConfiguration::get();
+
+ PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.begin();
+ for(; it != maPhysicalFontFamilies.end(); ++it )
+ {
+ const OUString& rSearchName = (*it).first;
+ PhysicalFontFamily* pEntry = (*it).second;
+
+ pEntry->InitMatchData( rFontSubst, rSearchName );
+ }
+}
+
+PhysicalFontFamily* PhysicalFontCollection::ImplFindByAttributes( sal_uLong nSearchType,
+ FontWeight eSearchWeight,
+ FontWidth eSearchWidth,
+ FontItalic eSearchItalic,
+ const OUString& rSearchFamilyName ) const
+{
+ if( (eSearchItalic != ITALIC_NONE) && (eSearchItalic != ITALIC_DONTKNOW) )
+ nSearchType |= IMPL_FONT_ATTR_ITALIC;
+
+ // don't bother to match attributes if the attributes aren't worth matching
+ if( !nSearchType
+ && ((eSearchWeight == WEIGHT_DONTKNOW) || (eSearchWeight == WEIGHT_NORMAL))
+ && ((eSearchWidth == WIDTH_DONTKNOW) || (eSearchWidth == WIDTH_NORMAL)) )
+ return NULL;
+
+ InitMatchData();
+ PhysicalFontFamily* pFoundData = NULL;
+
+ long nTestMatch;
+ long nBestMatch = 40000;
+ sal_uLong nBestType = 0;
+
+ PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.begin();
+ for(; it != maPhysicalFontFamilies.end(); ++it )
+ {
+ PhysicalFontFamily* pData = (*it).second;
+
+ // Get all information about the matching font
+ sal_uLong nMatchType = pData->GetMatchType();
+ FontWeight eMatchWeight= pData->GetMatchWeight();
+ FontWidth eMatchWidth = pData->GetMatchWidth();
+
+ // Calculate Match Value
+ // 1000000000
+ // 100000000
+ // 10000000 CJK, CTL, None-Latin, Symbol
+ // 1000000 FamilyName, Script, Fixed, -Special, -Decorative,
+ // Titling, Capitals, Outline, Shadow
+ // 100000 Match FamilyName, Serif, SansSerif, Italic,
+ // Width, Weight
+ // 10000 Scalable, Standard, Default,
+ // full, Normal, Knownfont,
+ // Otherstyle, +Special, +Decorative,
+ // 1000 Typewriter, Rounded, Gothic, Schollbook
+ // 100
+ nTestMatch = 0;
+
+ // test CJK script attributes
+ if ( nSearchType & IMPL_FONT_ATTR_CJK )
+ {
+ // Matching language
+ if( 0 == ((nSearchType ^ nMatchType) & IMPL_FONT_ATTR_CJK_ALLLANG) )
+ nTestMatch += 10000000*3;
+ if( nMatchType & IMPL_FONT_ATTR_CJK )
+ nTestMatch += 10000000*2;
+ if( nMatchType & IMPL_FONT_ATTR_FULL )
+ nTestMatch += 10000000;
+ }
+ else if ( nMatchType & IMPL_FONT_ATTR_CJK )
+ {
+ nTestMatch -= 10000000;
+ }
+
+ // test CTL script attributes
+ if( nSearchType & IMPL_FONT_ATTR_CTL )
+ {
+ if( nMatchType & IMPL_FONT_ATTR_CTL )
+ nTestMatch += 10000000*2;
+ if( nMatchType & IMPL_FONT_ATTR_FULL )
+ nTestMatch += 10000000;
+ }
+ else if ( nMatchType & IMPL_FONT_ATTR_CTL )
+ {
+ nTestMatch -= 10000000;
+ }
+
+ // test LATIN script attributes
+ if( nSearchType & IMPL_FONT_ATTR_NONELATIN )
+ {
+ if( nMatchType & IMPL_FONT_ATTR_NONELATIN )
+ nTestMatch += 10000000*2;
+ if( nMatchType & IMPL_FONT_ATTR_FULL )
+ nTestMatch += 10000000;
+ }
+
+ // test SYMBOL attributes
+ if ( nSearchType & IMPL_FONT_ATTR_SYMBOL )
+ {
+ const OUString& rSearchName = it->first;
+ // prefer some special known symbol fonts
+ if ( rSearchName == "starsymbol" )
+ {
+ nTestMatch += 10000000*6+(10000*3);
+ }
+ else if ( rSearchName == "opensymbol" )
+ {
+ nTestMatch += 10000000*6;
+ }
+ else if ( rSearchName == "starbats" ||
+ rSearchName == "wingdings" ||
+ rSearchName == "monotypesorts" ||
+ rSearchName == "dingbats" ||
+ rSearchName == "zapfdingbats" )
+ {
+ nTestMatch += 10000000*5;
+ }
+ else if ( pData->GetTypeFaces() & FONT_FAMILY_SYMBOL )
+ {
+ nTestMatch += 10000000*4;
+ }
+ else
+ {
+ if( nMatchType & IMPL_FONT_ATTR_SYMBOL )
+ nTestMatch += 10000000*2;
+ if( nMatchType & IMPL_FONT_ATTR_FULL )
+ nTestMatch += 10000000;
+ }
+ }
+ else if ( (pData->GetTypeFaces() & (FONT_FAMILY_SYMBOL | FONT_FAMILY_NONESYMBOL)) == FONT_FAMILY_SYMBOL )
+ {
+ nTestMatch -= 10000000;
+ }
+ else if ( nMatchType & IMPL_FONT_ATTR_SYMBOL )
+ {
+ nTestMatch -= 10000;
+ }
+
+ // match stripped family name
+ if( !rSearchFamilyName.isEmpty() && (rSearchFamilyName == pData->GetMatchFamilyName()) )
+ {
+ nTestMatch += 1000000*3;
+ }
+
+ // match ALLSCRIPT? attribute
+ if( nSearchType & IMPL_FONT_ATTR_ALLSCRIPT )
+ {
+ if( nMatchType & IMPL_FONT_ATTR_ALLSCRIPT )
+ {
+ nTestMatch += 1000000*2;
+ }
+ if( nSearchType & IMPL_FONT_ATTR_ALLSUBSCRIPT )
+ {
+ if( 0 == ((nSearchType ^ nMatchType) & IMPL_FONT_ATTR_ALLSUBSCRIPT) )
+ nTestMatch += 1000000*2;
+ if( 0 != ((nSearchType ^ nMatchType) & IMPL_FONT_ATTR_BRUSHSCRIPT) )
+ nTestMatch -= 1000000;
+ }
+ }
+ else if( nMatchType & IMPL_FONT_ATTR_ALLSCRIPT )
+ {
+ nTestMatch -= 1000000;
+ }
+
+ // test MONOSPACE+TYPEWRITER attributes
+ if( nSearchType & IMPL_FONT_ATTR_FIXED )
+ {
+ if( nMatchType & IMPL_FONT_ATTR_FIXED )
+ nTestMatch += 1000000*2;
+ // a typewriter attribute is even better
+ if( 0 == ((nSearchType ^ nMatchType) & IMPL_FONT_ATTR_TYPEWRITER) )
+ nTestMatch += 10000*2;
+ }
+ else if( nMatchType & IMPL_FONT_ATTR_FIXED )
+ {
+ nTestMatch -= 1000000;
+ }
+
+ // test SPECIAL attribute
+ if( nSearchType & IMPL_FONT_ATTR_SPECIAL )
+ {
+ if( nMatchType & IMPL_FONT_ATTR_SPECIAL )
+ {
+ nTestMatch += 10000;
+ }
+ else if( !(nSearchType & IMPL_FONT_ATTR_ALLSERIFSTYLE) )
+ {
+ if( nMatchType & IMPL_FONT_ATTR_SERIF )
+ {
+ nTestMatch += 1000*2;
+ }
+ else if( nMatchType & IMPL_FONT_ATTR_SANSSERIF )
+ {
+ nTestMatch += 1000;
+ }
+ }
+ }
+ else if( (nMatchType & IMPL_FONT_ATTR_SPECIAL) && !(nSearchType & IMPL_FONT_ATTR_SYMBOL) )
+ {
+ nTestMatch -= 1000000;
+ }
+
+ // test DECORATIVE attribute
+ if( nSearchType & IMPL_FONT_ATTR_DECORATIVE )
+ {
+ if( nMatchType & IMPL_FONT_ATTR_DECORATIVE )
+ {
+ nTestMatch += 10000;
+ }
+ else if( !(nSearchType & IMPL_FONT_ATTR_ALLSERIFSTYLE) )
+ {
+ if( nMatchType & IMPL_FONT_ATTR_SERIF )
+ nTestMatch += 1000*2;
+ else if ( nMatchType & IMPL_FONT_ATTR_SANSSERIF )
+ nTestMatch += 1000;
+ }
+ }
+ else if( nMatchType & IMPL_FONT_ATTR_DECORATIVE )
+ {
+ nTestMatch -= 1000000;
+ }
+
+ // test TITLE+CAPITALS attributes
+ if( nSearchType & (IMPL_FONT_ATTR_TITLING | IMPL_FONT_ATTR_CAPITALS) )
+ {
+ if( nMatchType & (IMPL_FONT_ATTR_TITLING | IMPL_FONT_ATTR_CAPITALS) )
+ {
+ nTestMatch += 1000000*2;
+ }
+ if( 0 == ((nSearchType^nMatchType) & (IMPL_FONT_ATTR_TITLING | IMPL_FONT_ATTR_CAPITALS)))
+ {
+ nTestMatch += 1000000;
+ }
+ else if( (nMatchType & (IMPL_FONT_ATTR_TITLING | IMPL_FONT_ATTR_CAPITALS)) &&
+ (nMatchType & (IMPL_FONT_ATTR_STANDARD | IMPL_FONT_ATTR_DEFAULT)) )
+ {
+ nTestMatch += 1000000;
+ }
+ }
+ else if( nMatchType & (IMPL_FONT_ATTR_TITLING | IMPL_FONT_ATTR_CAPITALS) )
+ {
+ nTestMatch -= 1000000;
+ }
+
+ // test OUTLINE+SHADOW attributes
+ if( nSearchType & (IMPL_FONT_ATTR_OUTLINE | IMPL_FONT_ATTR_SHADOW) )
+ {
+ if( nMatchType & (IMPL_FONT_ATTR_OUTLINE | IMPL_FONT_ATTR_SHADOW) )
+ {
+ nTestMatch += 1000000*2;
+ }
+ if( 0 == ((nSearchType ^ nMatchType) & (IMPL_FONT_ATTR_OUTLINE | IMPL_FONT_ATTR_SHADOW)) )
+ {
+ nTestMatch += 1000000;
+ }
+ else if( (nMatchType & (IMPL_FONT_ATTR_OUTLINE | IMPL_FONT_ATTR_SHADOW)) &&
+ (nMatchType & (IMPL_FONT_ATTR_STANDARD | IMPL_FONT_ATTR_DEFAULT)) )
+ {
+ nTestMatch += 1000000;
+ }
+ }
+ else if ( nMatchType & (IMPL_FONT_ATTR_OUTLINE | IMPL_FONT_ATTR_SHADOW) )
+ {
+ nTestMatch -= 1000000;
+ }
+
+ // test font name substrings
+ // TODO: calculate name matching score using e.g. Levenstein distance
+ if( (rSearchFamilyName.getLength() >= 4) &&
+ (pData->GetMatchFamilyName().getLength() >= 4) &&
+ ((rSearchFamilyName.indexOf( pData->GetMatchFamilyName() ) != -1) ||
+ (pData->GetMatchFamilyName().indexOf( rSearchFamilyName ) != -1)) )
+ {
+ nTestMatch += 5000;
+ }
+ // test SERIF attribute
+ if( nSearchType & IMPL_FONT_ATTR_SERIF )
+ {
+ if( nMatchType & IMPL_FONT_ATTR_SERIF )
+ nTestMatch += 1000000*2;
+ else if( nMatchType & IMPL_FONT_ATTR_SANSSERIF )
+ nTestMatch -= 1000000;
+ }
+
+ // test SANSERIF attribute
+ if( nSearchType & IMPL_FONT_ATTR_SANSSERIF )
+ {
+ if( nMatchType & IMPL_FONT_ATTR_SANSSERIF )
+ nTestMatch += 1000000;
+ else if ( nMatchType & IMPL_FONT_ATTR_SERIF )
+ nTestMatch -= 1000000;
+ }
+
+ // test ITALIC attribute
+ if( nSearchType & IMPL_FONT_ATTR_ITALIC )
+ {
+ if( pData->GetTypeFaces() & FONT_FAMILY_ITALIC )
+ nTestMatch += 1000000*3;
+ if( nMatchType & IMPL_FONT_ATTR_ITALIC )
+ nTestMatch += 1000000;
+ }
+ else if( !(nSearchType & IMPL_FONT_ATTR_ALLSCRIPT) &&
+ ((nMatchType & IMPL_FONT_ATTR_ITALIC) ||
+ !(pData->GetTypeFaces() & FONT_FAMILY_NONEITALIC)) )
+ {
+ nTestMatch -= 1000000*2;
+ }
+
+ // test WIDTH attribute
+ if( (eSearchWidth != WIDTH_DONTKNOW) && (eSearchWidth != WIDTH_NORMAL) )
+ {
+ if( eSearchWidth < WIDTH_NORMAL )
+ {
+ if( eSearchWidth == eMatchWidth )
+ nTestMatch += 1000000*3;
+ else if( (eMatchWidth < WIDTH_NORMAL) && (eMatchWidth != WIDTH_DONTKNOW) )
+ nTestMatch += 1000000;
+ }
+ else
+ {
+ if( eSearchWidth == eMatchWidth )
+ nTestMatch += 1000000*3;
+ else if( eMatchWidth > WIDTH_NORMAL )
+ nTestMatch += 1000000;
+ }
+ }
+ else if( (eMatchWidth != WIDTH_DONTKNOW) && (eMatchWidth != WIDTH_NORMAL) )
+ {
+ nTestMatch -= 1000000;
+ }
+
+ // test WEIGHT attribute
+ if( (eSearchWeight != WEIGHT_DONTKNOW) &&
+ (eSearchWeight != WEIGHT_NORMAL) &&
+ (eSearchWeight != WEIGHT_MEDIUM) )
+ {
+ if( eSearchWeight < WEIGHT_NORMAL )
+ {
+ if( pData->GetTypeFaces() & FONT_FAMILY_LIGHT )
+ nTestMatch += 1000000;
+ if( (eMatchWeight < WEIGHT_NORMAL) && (eMatchWeight != WEIGHT_DONTKNOW) )
+ nTestMatch += 1000000;
+ }
+ else
+ {
+ if( pData->GetTypeFaces() & FONT_FAMILY_BOLD )
+ nTestMatch += 1000000;
+ if( eMatchWeight > WEIGHT_BOLD )
+ nTestMatch += 1000000;
+ }
+ }
+ else if( ((eMatchWeight != WEIGHT_DONTKNOW) &&
+ (eMatchWeight != WEIGHT_NORMAL) &&
+ (eMatchWeight != WEIGHT_MEDIUM)) ||
+ !(pData->GetTypeFaces() & FONT_FAMILY_NORMAL) )
+ {
+ nTestMatch -= 1000000;
+ }
+
+ // prefer scalable fonts
+ if( pData->GetTypeFaces() & FONT_FAMILY_SCALABLE )
+ nTestMatch += 10000*4;
+ else
+ nTestMatch -= 10000*4;
+
+ // test STANDARD+DEFAULT+FULL+NORMAL attributes
+ if( nMatchType & IMPL_FONT_ATTR_STANDARD )
+ nTestMatch += 10000*2;
+ if( nMatchType & IMPL_FONT_ATTR_DEFAULT )
+ nTestMatch += 10000;
+ if( nMatchType & IMPL_FONT_ATTR_FULL )
+ nTestMatch += 10000;
+ if( nMatchType & IMPL_FONT_ATTR_NORMAL )
+ nTestMatch += 10000;
+
+ // test OTHERSTYLE attribute
+ if( ((nSearchType ^ nMatchType) & IMPL_FONT_ATTR_OTHERSTYLE) != 0 )
+ {
+ nTestMatch -= 10000;
+ }
+
+ // test ROUNDED attribute
+ if( 0 == ((nSearchType ^ nMatchType) & IMPL_FONT_ATTR_ROUNDED) )
+ nTestMatch += 1000;
+
+ // test TYPEWRITER attribute
+ if( 0 == ((nSearchType ^ nMatchType) & IMPL_FONT_ATTR_TYPEWRITER) )
+ nTestMatch += 1000;
+
+ // test GOTHIC attribute
+ if( nSearchType & IMPL_FONT_ATTR_GOTHIC )
+ {
+ if( nMatchType & IMPL_FONT_ATTR_GOTHIC )
+ nTestMatch += 1000*3;
+ if( nMatchType & IMPL_FONT_ATTR_SANSSERIF )
+ nTestMatch += 1000*2;
+ }
+
+ // test SCHOOLBOOK attribute
+ if( nSearchType & IMPL_FONT_ATTR_SCHOOLBOOK )
+ {
+ if( nMatchType & IMPL_FONT_ATTR_SCHOOLBOOK )
+ nTestMatch += 1000*3;
+ if( nMatchType & IMPL_FONT_ATTR_SERIF )
+ nTestMatch += 1000*2;
+ }
+
+ // compare with best matching font yet
+ if ( nTestMatch > nBestMatch )
+ {
+ pFoundData = pData;
+ nBestMatch = nTestMatch;
+ nBestType = nMatchType;
+ }
+ else if( nTestMatch == nBestMatch )
+ {
+ // some fonts are more suitable defaults
+ if( nMatchType & IMPL_FONT_ATTR_DEFAULT )
+ {
+ pFoundData = pData;
+ nBestType = nMatchType;
+ }
+ else if( (nMatchType & IMPL_FONT_ATTR_STANDARD) &&
+ !(nBestType & IMPL_FONT_ATTR_DEFAULT) )
+ {
+ pFoundData = pData;
+ nBestType = nMatchType;
+ }
+ }
+ }
+
+ return pFoundData;
+}
+
+PhysicalFontFamily* PhysicalFontCollection::FindDefaultFont() const
+{
+ // try to find one of the default fonts of the
+ // UNICODE, SANSSERIF, SERIF or FIXED default font lists
+ const utl::DefaultFontConfiguration& rDefaults = utl::DefaultFontConfiguration::get();
+ LanguageTag aLanguageTag( OUString( "en"));
+ OUString aFontname = rDefaults.getDefaultFont( aLanguageTag, DEFAULTFONT_SANS_UNICODE );
+ PhysicalFontFamily* pFoundData = ImplFindByTokenNames( aFontname );
+
+ if( pFoundData )
+ return pFoundData;
+
+ aFontname = rDefaults.getDefaultFont( aLanguageTag, DEFAULTFONT_SANS );
+ pFoundData = ImplFindByTokenNames( aFontname );
+ if( pFoundData )
+ return pFoundData;
+
+ aFontname = rDefaults.getDefaultFont( aLanguageTag, DEFAULTFONT_SERIF );
+ pFoundData = ImplFindByTokenNames( aFontname );
+ if( pFoundData )
+ return pFoundData;
+
+ aFontname = rDefaults.getDefaultFont( aLanguageTag, DEFAULTFONT_FIXED );
+ pFoundData = ImplFindByTokenNames( aFontname );
+ if( pFoundData )
+ return pFoundData;
+
+ // now try to find a reasonable non-symbol font
+
+ InitMatchData();
+
+ PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.begin();
+ for(; it != maPhysicalFontFamilies.end(); ++it )
+ {
+ PhysicalFontFamily* pData = (*it).second;
+ if( pData->GetMatchType() & IMPL_FONT_ATTR_SYMBOL )
+ continue;
+
+ pFoundData = pData;
+ if( pData->GetMatchType() & (IMPL_FONT_ATTR_DEFAULT|IMPL_FONT_ATTR_STANDARD) )
+ break;
+ }
+ if( pFoundData )
+ return pFoundData;
+
+ // finding any font is better than finding no font at all
+ it = maPhysicalFontFamilies.begin();
+ if( it != maPhysicalFontFamilies.end() )
+ pFoundData = (*it).second;
+
+ return pFoundData;
+}
+
+PhysicalFontCollection* PhysicalFontCollection::Clone( bool bScalable, bool bEmbeddable ) const
+{
+ PhysicalFontCollection* pClonedCollection = new PhysicalFontCollection;
+ pClonedCollection->mbMapNames = mbMapNames;
+ pClonedCollection->mpPreMatchHook = mpPreMatchHook;
+ pClonedCollection->mpFallbackHook = mpFallbackHook;
+
+ // TODO: clone the config-font attributes too?
+ pClonedCollection->mbMatchData = false;
+
+ PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.begin();
+ for(; it != maPhysicalFontFamilies.end(); ++it )
+ {
+ const PhysicalFontFamily* pFontFace = (*it).second;
+ pFontFace->UpdateCloneFontList( *pClonedCollection, bScalable, bEmbeddable );
+ }
+
+ return pClonedCollection;
+}
+
+ImplGetDevFontList* PhysicalFontCollection::GetDevFontList() const
+{
+ ImplGetDevFontList* pGetDevFontList = new ImplGetDevFontList;
+
+ PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.begin();
+ for(; it != maPhysicalFontFamilies.end(); ++it )
+ {
+ const PhysicalFontFamily* pFontFamily = (*it).second;
+ pFontFamily->UpdateDevFontList( *pGetDevFontList );
+ }
+
+ return pGetDevFontList;
+}
+
+ImplGetDevSizeList* PhysicalFontCollection::GetDevSizeList( const OUString& rFontName ) const
+{
+ ImplGetDevSizeList* pGetDevSizeList = new ImplGetDevSizeList( rFontName );
+
+ PhysicalFontFamily* pFontFamily = FindFontFamily( rFontName );
+ if( pFontFamily != NULL )
+ {
+ std::set<int> rHeights;
+ pFontFamily->GetFontHeights( rHeights );
+
+ std::set<int>::const_iterator it = rHeights.begin();
+ for(; it != rHeights.begin(); ++it )
+ pGetDevSizeList->Add( *it );
+ }
+
+ return pGetDevSizeList;
+}
+
+PhysicalFontFamily* PhysicalFontCollection::ImplFindByFont( FontSelectPattern& rFSD ) const
+{
+ // give up if no fonts are available
+ if( !Count() )
+ return NULL;
+
+ bool bMultiToken = false;
+ sal_Int32 nTokenPos = 0;
+ OUString& aSearchName = rFSD.maSearchName; // TODO: get rid of reference
+ for(;;)
+ {
+ rFSD.maTargetName = GetNextFontToken( rFSD.GetFamilyName(), nTokenPos );
+ aSearchName = rFSD.maTargetName;
+
+#if ENABLE_GRAPHITE
+ // Until features are properly supported, they are appended to the
+ // font name, so we need to strip them off so the font is found.
+ sal_Int32 nFeat = aSearchName.indexOf(grutils::GrFeatureParser::FEAT_PREFIX);
+ OUString aOrigName = rFSD.maTargetName;
+ OUString aBaseFontName = aSearchName.copy( 0, (nFeat != -1) ? nFeat : aSearchName.getLength() );
+
+ if (nFeat != -1 &&
+ -1 != aSearchName.indexOf(grutils::GrFeatureParser::FEAT_ID_VALUE_SEPARATOR, nFeat))
+ {
+ aSearchName = aBaseFontName;
+ rFSD.maTargetName = aBaseFontName;
+ }
+
+#endif
+
+ GetEnglishSearchFontName( aSearchName );
+ ImplFontSubstitute( aSearchName );
+ // #114999# special emboldening for Ricoh fonts
+ // TODO: smarter check for special cases by using PreMatch infrastructure?
+ if( (rFSD.GetWeight() > WEIGHT_MEDIUM) &&
+ aSearchName.startsWithIgnoreAsciiCase( "hg" ) )
+ {
+ OUString aBoldName;
+ if( aSearchName.startsWithIgnoreAsciiCase( "hggothicb" ) )
+ aBoldName = "hggothice";
+ else if( aSearchName.startsWithIgnoreAsciiCase( "hgpgothicb" ) )
+ aBoldName = "hgpgothice";
+ else if( aSearchName.startsWithIgnoreAsciiCase( "hgminchol" ) )
+ aBoldName = "hgminchob";
+ else if( aSearchName.startsWithIgnoreAsciiCase( "hgpminchol" ) )
+ aBoldName = "hgpminchob";
+ else if( aSearchName.equalsIgnoreAsciiCase( "hgminchob" ) )
+ aBoldName = "hgminchoe";
+ else if( aSearchName.equalsIgnoreAsciiCase( "hgpminchob" ) )
+ aBoldName = "hgpminchoe";
+
+ if( !aBoldName.isEmpty() && ImplFindBySearchName( aBoldName ) )
+ {
+ // the other font is available => use it
+ aSearchName = aBoldName;
+ // prevent synthetic emboldening of bold version
+ rFSD.SetWeight(WEIGHT_DONTKNOW);
+ }
+ }
+
+#if ENABLE_GRAPHITE
+ // restore the features to make the font selection data unique
+ rFSD.maTargetName = aOrigName;
+#endif
+ // check if the current font name token or its substitute is valid
+ PhysicalFontFamily* pFoundData = ImplFindBySearchName( aSearchName );
+ if( pFoundData )
+ return pFoundData;
+
+ // some systems provide special customization
+ // e.g. they suggest "serif" as UI-font, but this name cannot be used directly
+ // because the system wants to map it to another font first, e.g. "Helvetica"
+#if ENABLE_GRAPHITE
+ // use the target name to search in the prematch hook
+ rFSD.maTargetName = aBaseFontName;
+#endif
+
+ // Related: fdo#49271 RTF files often contain weird-ass
+ // Win 3.1/Win95 style fontnames which attempt to put the
+ // charset encoding into the filename
+ // http://www.webcenter.ru/~kazarn/eng/fonts_ttf.htm
+ OUString sStrippedName = lcl_stripCharSetFromName(rFSD.maTargetName);
+ if (sStrippedName != rFSD.maTargetName)
+ {
+ rFSD.maTargetName = sStrippedName;
+ aSearchName = rFSD.maTargetName;
+ GetEnglishSearchFontName(aSearchName);
+ pFoundData = ImplFindBySearchName(aSearchName);
+ if( pFoundData )
+ return pFoundData;
+ }
+
+ if( mpPreMatchHook )
+ {
+ if( mpPreMatchHook->FindFontSubstitute( rFSD ) )
+ GetEnglishSearchFontName( aSearchName );
+ }
+#if ENABLE_GRAPHITE
+ // the prematch hook uses the target name to search, but we now need
+ // to restore the features to make the font selection data unique
+ rFSD.maTargetName = aOrigName;
+#endif
+ pFoundData = ImplFindBySearchName( aSearchName );
+ if( pFoundData )
+ return pFoundData;
+
+ // break after last font name token was checked unsuccessfully
+ if( nTokenPos == -1)
+ break;
+ bMultiToken = true;
+ }
+
+ // if the first font was not available find the next available font in
+ // the semicolon separated list of font names. A font is also considered
+ // available when there is a matching entry in the Tools->Options->Fonts
+ // dialog witho neither ALWAYS nor SCREENONLY flags set and the substitution
+ // font is available
+ for( nTokenPos = 0; nTokenPos != -1; )
+ {
+ if( bMultiToken )
+ {
+ rFSD.maTargetName = GetNextFontToken( rFSD.GetFamilyName(), nTokenPos );
+ aSearchName = rFSD.maTargetName;
+ GetEnglishSearchFontName( aSearchName );
+ }
+ else
+ nTokenPos = -1;
+ if( mpPreMatchHook )
+ if( mpPreMatchHook->FindFontSubstitute( rFSD ) )
+ GetEnglishSearchFontName( aSearchName );
+ ImplFontSubstitute( aSearchName );
+ PhysicalFontFamily* pFoundData = ImplFindBySearchName( aSearchName );
+ if( pFoundData )
+ return pFoundData;
+ }
+
+ // if no font with a directly matching name is available use the
+ // first font name token and get its attributes to find a replacement
+ if ( bMultiToken )
+ {
+ nTokenPos = 0;
+ rFSD.maTargetName = GetNextFontToken( rFSD.GetFamilyName(), nTokenPos );
+ aSearchName = rFSD.maTargetName;
+ GetEnglishSearchFontName( aSearchName );
+ }
+
+ OUString aSearchShortName;
+ OUString aSearchFamilyName;
+ FontWeight eSearchWeight = rFSD.GetWeight();
+ FontWidth eSearchWidth = rFSD.GetWidthType();
+ sal_uLong nSearchType = 0;
+ utl::FontSubstConfiguration::getMapName( aSearchName, aSearchShortName, aSearchFamilyName,
+ eSearchWeight, eSearchWidth, nSearchType );
+
+ // note: the search name was already translated to english (if possible)
+ // use the font's shortened name if needed
+ if ( aSearchShortName != aSearchName )
+ {
+ PhysicalFontFamily* pFoundData = ImplFindBySearchName( aSearchShortName );
+ if( pFoundData )
+ {
+#ifdef UNX
+ /* #96738# don't use mincho as an replacement for "MS Mincho" on X11: Mincho is
+ a korean bitmap font that is not suitable here. Use the font replacement table,
+ that automatically leads to the desired "HG Mincho Light J". Same story for
+ MS Gothic, there are thai and korean "Gothic" fonts, so we even prefer Andale */
+ static OUString aMS_Mincho( "msmincho" );
+ static OUString aMS_Gothic( "msgothic" );
+ if ((aSearchName != aMS_Mincho) && (aSearchName != aMS_Gothic))
+ // TODO: add heuristic to only throw out the fake ms* fonts
+#endif
+ {
+ return pFoundData;
+ }
+ }
+ }
+
+ // use font fallback
+ const utl::FontNameAttr* pFontAttr = NULL;
+ if( !aSearchName.isEmpty() )
+ {
+ // get fallback info using FontSubstConfiguration and
+ // the target name, it's shortened name and family name in that order
+ const utl::FontSubstConfiguration& rFontSubst = utl::FontSubstConfiguration::get();
+ pFontAttr = rFontSubst.getSubstInfo( aSearchName );
+ if ( !pFontAttr && (aSearchShortName != aSearchName) )
+ pFontAttr = rFontSubst.getSubstInfo( aSearchShortName );
+ if ( !pFontAttr && (aSearchFamilyName != aSearchShortName) )
+ pFontAttr = rFontSubst.getSubstInfo( aSearchFamilyName );
+
+ // try the font substitutions suggested by the fallback info
+ if( pFontAttr )
+ {
+ PhysicalFontFamily* pFoundData = ImplFindBySubstFontAttr( *pFontAttr );
+ if( pFoundData )
+ return pFoundData;
+ }
+ }
+
+ // if a target symbol font is not available use a default symbol font
+ if( rFSD.IsSymbolFont() )
+ {
+ LanguageTag aDefaultLanguageTag( OUString( "en"));
+ aSearchName = utl::DefaultFontConfiguration::get().getDefaultFont( aDefaultLanguageTag, DEFAULTFONT_SYMBOL );
+ PhysicalFontFamily* pFoundData = ImplFindByTokenNames( aSearchName );
+ if( pFoundData )
+ return pFoundData;
+ }
+
+ // now try the other font name tokens
+ while( nTokenPos != -1 )
+ {
+ rFSD.maTargetName = GetNextFontToken( rFSD.GetFamilyName(), nTokenPos );
+ if( rFSD.maTargetName.isEmpty() )
+ continue;
+
+ aSearchName = rFSD.maTargetName;
+ GetEnglishSearchFontName( aSearchName );
+
+ OUString aTempShortName;
+ OUString aTempFamilyName;
+ sal_uLong nTempType = 0;
+ FontWeight eTempWeight = rFSD.GetWeight();
+ FontWidth eTempWidth = WIDTH_DONTKNOW;
+ utl::FontSubstConfiguration::getMapName( aSearchName, aTempShortName, aTempFamilyName,
+ eTempWeight, eTempWidth, nTempType );
+
+ // use a shortend token name if available
+ if( aTempShortName != aSearchName )
+ {
+ PhysicalFontFamily* pFoundData = ImplFindBySearchName( aTempShortName );
+ if( pFoundData )
+ return pFoundData;
+ }
+
+ // use a font name from font fallback list to determine font attributes
+ // get fallback info using FontSubstConfiguration and
+ // the target name, it's shortened name and family name in that order
+ const utl::FontSubstConfiguration& rFontSubst = utl::FontSubstConfiguration::get();
+ const utl::FontNameAttr* pTempFontAttr = rFontSubst.getSubstInfo( aSearchName );
+
+ if ( !pTempFontAttr && (aTempShortName != aSearchName) )
+ pTempFontAttr = rFontSubst.getSubstInfo( aTempShortName );
+
+ if ( !pTempFontAttr && (aTempFamilyName != aTempShortName) )
+ pTempFontAttr = rFontSubst.getSubstInfo( aTempFamilyName );
+
+ // try the font substitutions suggested by the fallback info
+ if( pTempFontAttr )
+ {
+ PhysicalFontFamily* pFoundData = ImplFindBySubstFontAttr( *pTempFontAttr );
+ if( pFoundData )
+ return pFoundData;
+ if( !pFontAttr )
+ pFontAttr = pTempFontAttr;
+ }
+ }
+
+ // if still needed use the alias names of the installed fonts
+ if( mbMapNames )
+ {
+ PhysicalFontFamily* pFoundData = ImplFindByAliasName( rFSD.maTargetName, aSearchShortName );
+ if( pFoundData )
+ return pFoundData;
+ }
+
+ // if still needed use the font request's attributes to find a good match
+ if (MsLangId::isSimplifiedChinese(rFSD.meLanguage))
+ nSearchType |= IMPL_FONT_ATTR_CJK | IMPL_FONT_ATTR_CJK_SC;
+ else if (MsLangId::isTraditionalChinese(rFSD.meLanguage))
+ nSearchType |= IMPL_FONT_ATTR_CJK | IMPL_FONT_ATTR_CJK_TC;
+ else if (MsLangId::isKorean(rFSD.meLanguage))
+ nSearchType |= IMPL_FONT_ATTR_CJK | IMPL_FONT_ATTR_CJK_KR;
+ else if (rFSD.meLanguage == LANGUAGE_JAPANESE)
+ nSearchType |= IMPL_FONT_ATTR_CJK | IMPL_FONT_ATTR_CJK_JP;
+ else
+ {
+ nSearchType |= lcl_IsCJKFont( rFSD.GetFamilyName() );
+ if( rFSD.IsSymbolFont() )
+ nSearchType |= IMPL_FONT_ATTR_SYMBOL;
+ }
+
+ PhysicalFontFamily::CalcType( nSearchType, eSearchWeight, eSearchWidth, rFSD.GetFamilyType(), pFontAttr );
+ PhysicalFontFamily* pFoundData = ImplFindByAttributes( nSearchType,
+ eSearchWeight, eSearchWidth, rFSD.GetSlant(), aSearchFamilyName );
+
+ if( pFoundData )
+ {
+ // overwrite font selection attributes using info from the typeface flags
+ if( (eSearchWeight >= WEIGHT_BOLD) &&
+ (eSearchWeight > rFSD.GetWeight()) &&
+ (pFoundData->GetTypeFaces() & FONT_FAMILY_BOLD) )
+ {
+ rFSD.SetWeight( eSearchWeight );
+ }
+ else if( (eSearchWeight < WEIGHT_NORMAL) &&
+ (eSearchWeight < rFSD.GetWeight()) &&
+ (eSearchWeight != WEIGHT_DONTKNOW) &&
+ (pFoundData->GetTypeFaces() & FONT_FAMILY_LIGHT) )
+ {
+ rFSD.SetWeight( eSearchWeight );
+ }
+
+ if( (nSearchType & IMPL_FONT_ATTR_ITALIC) &&
+ ((rFSD.GetSlant() == ITALIC_DONTKNOW) ||
+ (rFSD.GetSlant() == ITALIC_NONE)) &&
+ (pFoundData->GetTypeFaces() & FONT_FAMILY_ITALIC) )
+ {
+ rFSD.SetItalic( ITALIC_NORMAL );
+ }
+ }
+ else
+ {
+ // if still needed fall back to default fonts
+ pFoundData = FindDefaultFont();
+ }
+
+ return pFoundData;
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
+
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: */
diff --git a/vcl/source/gdi/embeddedfontshelper.cxx b/vcl/source/gdi/embeddedfontshelper.cxx
index 3e4d94694638..05730b7cc959 100644
--- a/vcl/source/gdi/embeddedfontshelper.cxx
+++ b/vcl/source/gdi/embeddedfontshelper.cxx
@@ -8,23 +8,23 @@
*/
#include <config_folders.h>
+#include <config_eot.h>
-#include <vcl/embeddedfontshelper.hxx>
-
+#include <boost/scoped_ptr.hpp>
+#include <boost/shared_ptr.hpp>
#include <osl/file.hxx>
#include <rtl/bootstrap.hxx>
-#include <sft.hxx>
#include <vcl/outdev.hxx>
#include <vcl/svapp.hxx>
-#include <boost/scoped_ptr.hpp>
-#include <boost/shared_ptr.hpp>
-#include <fontsubset.hxx>
-#include <outdev.h>
-#include <outfont.hxx>
-#include <salgdi.hxx>
+#include "fontsubset.hxx"
+#include "outdev.h"
+#include "outfont.hxx"
+#include "PhysicalFontCollection.hxx"
+#include "salgdi.hxx"
+#include "sft.hxx"
-#include <config_eot.h>
+#include <vcl/embeddedfontshelper.hxx>
#if ENABLE_EOT
extern "C"
diff --git a/vcl/source/gdi/outdev.cxx b/vcl/source/gdi/outdev.cxx
index 1939e2ea3111..762f2bdb3729 100644
--- a/vcl/source/gdi/outdev.cxx
+++ b/vcl/source/gdi/outdev.cxx
@@ -43,6 +43,7 @@
#include <window.h>
#include <outdev.h>
#include <outdata.hxx>
+#include "PhysicalFontCollection.hxx"
#include <basegfx/point/b2dpoint.hxx>
#include <basegfx/vector/b2dvector.hxx>
diff --git a/vcl/source/gdi/outdev3.cxx b/vcl/source/gdi/outdev3.cxx
index 8dd4b9206302..7de3d81c0c19 100644
--- a/vcl/source/gdi/outdev3.cxx
+++ b/vcl/source/gdi/outdev3.cxx
@@ -55,6 +55,10 @@
#include "outdata.hxx"
#include "outfont.hxx"
#include "outdev.h"
+#include "PhysicalFontCollection.hxx"
+#include "PhysicalFontFace.hxx"
+#include "PhysicalFontFamily.hxx"
+
#include "textlayout.hxx"
#include "svids.hrc"
#include "window.h"
@@ -424,7 +428,7 @@ bool ImplDirectFontSubstitution::FindFontSubstitute( OUString& rSubstName,
return false;
}
-static void ImplFontSubstitute( OUString& rFontName )
+void ImplFontSubstitute( OUString& rFontName )
{
#ifdef DBG_UTIL
OUString aTempName = rFontName;
@@ -637,67 +641,6 @@ Font OutputDevice::GetDefaultFont( sal_uInt16 nType, LanguageType eLang,
return aFont;
}
-static unsigned ImplIsCJKFont( 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;
-}
-
-static void ImplCalcType( sal_uLong& rType, FontWeight& rWeight, FontWidth& rWidth,
- FontFamily eFamily, const 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;
- }
-}
ImplFontEntry::ImplFontEntry( const FontSelectPattern& rFontSelData )
: maFontSelData( rFontSelData )
@@ -726,14 +669,14 @@ size_t ImplFontEntry::GFBCacheKey_Hash::operator()( const GFBCacheKey& rData ) c
return a(rData.first) ^ b(rData.second);
}
-inline void ImplFontEntry::AddFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName )
+void ImplFontEntry::AddFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName )
{
if( !mpUnicodeFallbackList )
mpUnicodeFallbackList = new UnicodeFallbackList;
(*mpUnicodeFallbackList)[ GFBCacheKey(cChar,eWeight) ] = rFontName;
}
-inline bool ImplFontEntry::GetFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, OUString* pFontName ) const
+bool ImplFontEntry::GetFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, OUString* pFontName ) const
{
if( !mpUnicodeFallbackList )
return false;
@@ -746,7 +689,7 @@ inline bool ImplFontEntry::GetFallbackForUnicode( sal_UCS4 cChar, FontWeight eWe
return true;
}
-inline void ImplFontEntry::IgnoreFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName )
+void ImplFontEntry::IgnoreFallbackForUnicode( sal_UCS4 cChar, FontWeight eWeight, const OUString& rFontName )
{
// DBG_ASSERT( mpUnicodeFallbackList, "ImplFontEntry::IgnoreFallbackForUnicode no list" );
UnicodeFallbackList::iterator it = mpUnicodeFallbackList->find( GFBCacheKey(cChar,eWeight) );
@@ -757,1056 +700,6 @@ inline void ImplFontEntry::IgnoreFallbackForUnicode( sal_UCS4 cChar, FontWeight
mpUnicodeFallbackList->erase( it );
}
-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 |= IMPL_DEVFONT_SCALABLE;
-
- if( pNewData->IsSymbolFont() )
- mnTypeFaces |= IMPL_DEVFONT_SYMBOL;
- else
- mnTypeFaces |= IMPL_DEVFONT_NONESYMBOL;
-
- if( pNewData->GetWeight() != WEIGHT_DONTKNOW )
- {
- if( pNewData->GetWeight() >= WEIGHT_SEMIBOLD )
- mnTypeFaces |= IMPL_DEVFONT_BOLD;
- else if( pNewData->GetWeight() <= WEIGHT_SEMILIGHT )
- mnTypeFaces |= IMPL_DEVFONT_LIGHT;
- else
- mnTypeFaces |= IMPL_DEVFONT_NORMAL;
- }
-
- if( pNewData->GetSlant() == ITALIC_NONE )
- mnTypeFaces |= IMPL_DEVFONT_NONEITALIC;
- else if( (pNewData->GetSlant() == ITALIC_NORMAL)
- || (pNewData->GetSlant() == ITALIC_OBLIQUE) )
- mnTypeFaces |= IMPL_DEVFONT_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 FontNameAttr* pFontAttr = rFontSubst.getSubstInfo( rSearchName );
- // eventually use the stripped name
- if( !pFontAttr )
- if( aShortName != rSearchName )
- pFontAttr = rFontSubst.getSubstInfo( aShortName );
- ImplCalcType( mnMatchType, meMatchWeight, meMatchWidth, meFamily, pFontAttr );
- mnMatchType |= ImplIsCJKFont( 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 );
- }
-}
-
-PhysicalFontCollection::PhysicalFontCollection()
-: mbMatchData( false )
-, mbMapNames( false )
-, mpPreMatchHook( NULL )
-, mpFallbackHook( NULL )
-, mpFallbackList( NULL )
-, mnFallbackCount( -1 )
-{}
-
-PhysicalFontCollection::~PhysicalFontCollection()
-{
- Clear();
-}
-
-void PhysicalFontCollection::SetPreMatchHook( ImplPreMatchFontSubstitution* pHook )
-{
- mpPreMatchHook = pHook;
-}
-
-void PhysicalFontCollection::SetFallbackHook( ImplGlyphFallbackFontSubstitution* pHook )
-{
- mpFallbackHook = pHook;
-}
-
-void PhysicalFontCollection::Clear()
-{
- // remove fallback lists
- delete[] mpFallbackList;
- mpFallbackList = NULL;
- mnFallbackCount = -1;
-
- // clear all entries in the device font list
- PhysicalFontFamilies::iterator it = maPhysicalFontFamilies.begin();
- for(; it != maPhysicalFontFamilies.end(); ++it )
- {
- PhysicalFontFamily* pEntry = (*it).second;
- delete pEntry;
- }
-
- maPhysicalFontFamilies.clear();
-
- // match data must be recalculated too
- mbMatchData = false;
-}
-
-void PhysicalFontCollection::InitGenericGlyphFallback( void ) const
-{
- // normalized family names of fonts suited for glyph fallback
- // if a font is available related fonts can be ignored
- // TODO: implement dynamic lists
- static const char* aGlyphFallbackList[] = {
- // empty strings separate the names of unrelated fonts
- "eudc", "",
- "arialunicodems", "cyberbit", "code2000", "",
- "andalesansui", "",
- "starsymbol", "opensymbol", "",
- "msmincho", "fzmingti", "fzheiti", "ipamincho", "sazanamimincho", "kochimincho", "",
- "sunbatang", "sundotum", "baekmukdotum", "gulim", "batang", "dotum", "",
- "hgmincholightj", "msunglightsc", "msunglighttc", "hymyeongjolightk", "",
- "tahoma", "dejavusans", "timesnewroman", "liberationsans", "",
- "shree", "mangal", "",
- "raavi", "shruti", "tunga", "",
- "latha", "gautami", "kartika", "vrinda", "",
- "shayyalmt", "naskmt", "scheherazade", "",
- "david", "nachlieli", "lucidagrande", "",
- "norasi", "angsanaupc", "",
- "khmerossystem", "",
- "muktinarrow", "",
- "phetsarathot", "",
- "padauk", "pinlonmyanmar", "",
- "iskoolapota", "lklug", "",
- 0
- };
-
- bool bHasEudc = false;
- int nMaxLevel = 0;
- int nBestQuality = 0;
- PhysicalFontFamily** pFallbackList = NULL;
- for( const char** ppNames = &aGlyphFallbackList[0];; ++ppNames )
- {
- // advance to next sub-list when end-of-sublist marker
- if( !**ppNames ) // #i46456# check for empty string, i.e., deref string itself not only ptr to it
- {
- if( nBestQuality > 0 )
- if( ++nMaxLevel >= MAX_FALLBACK )
- break;
- if( !ppNames[1] )
- break;
- nBestQuality = 0;
- continue;
- }
-
- // test if the glyph fallback candidate font is available and scalable
- OUString aTokenName( *ppNames, strlen(*ppNames), RTL_TEXTENCODING_UTF8 );
- PhysicalFontFamily* pFallbackFont = FindFontFamily( aTokenName );
- if( !pFallbackFont )
- continue;
- if( !pFallbackFont->IsScalable() )
- continue;
-
- // keep the best font of the glyph fallback sub-list
- if( nBestQuality < pFallbackFont->GetMinQuality() )
- {
- nBestQuality = pFallbackFont->GetMinQuality();
- // store available glyph fallback fonts
- if( !pFallbackList )
- pFallbackList = new PhysicalFontFamily*[ MAX_FALLBACK ];
- pFallbackList[ nMaxLevel ] = pFallbackFont;
- if( !bHasEudc && !nMaxLevel )
- bHasEudc = !strncmp( *ppNames, "eudc", 5 );
- }
- }
-
-#ifdef SAL_FONTENUM_STABLE_ON_PLATFORM // #i113472#
- // sort the list of fonts for glyph fallback by quality (highest first)
- // #i33947# keep the EUDC font at the front of the list
- // an insertion sort is good enough for this short list
- const int nSortStart = bHasEudc ? 1 : 0;
- for( int i = nSortStart+1, j; i < nMaxLevel; ++i )
- {
- PhysicalFontFamily* pTestFont = pFallbackList[ i ];
- int nTestQuality = pTestFont->GetMinQuality();
- for( j = i; --j >= nSortStart; )
- if( nTestQuality > pFallbackList[j]->GetMinQuality() )
- pFallbackList[ j+1 ] = pFallbackList[ j ];
- else
- break;
- pFallbackList[ j+1 ] = pTestFont;
- }
-#endif
-
- mnFallbackCount = nMaxLevel;
- mpFallbackList = pFallbackList;
-}
-
-PhysicalFontFamily* PhysicalFontCollection::GetGlyphFallbackFont( FontSelectPattern& rFontSelData,
- OUString& rMissingCodes, int nFallbackLevel ) const
-{
- PhysicalFontFamily* pFallbackData = NULL;
-
- // find a matching font candidate for platform specific glyph fallback
- if( mpFallbackHook )
- {
- // check cache for the first matching entry
- // to avoid calling the expensive fallback hook (#i83491#)
- sal_UCS4 cChar = 0;
- bool bCached = true;
- sal_Int32 nStrIndex = 0;
- while( nStrIndex < rMissingCodes.getLength() )
- {
- cChar = rMissingCodes.iterateCodePoints( &nStrIndex );
- bCached = rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &rFontSelData.maSearchName );
- // ignore entries which don't have a fallback
- if( !bCached || !rFontSelData.maSearchName.isEmpty() )
- break;
- }
-
- if( bCached )
- {
- // there is a matching fallback in the cache
- // so update rMissingCodes with codepoints not yet resolved by this fallback
- int nRemainingLength = 0;
- sal_UCS4* pRemainingCodes = (sal_UCS4*)alloca( rMissingCodes.getLength() * sizeof(sal_UCS4) );
- OUString aFontName;
- while( nStrIndex < rMissingCodes.getLength() )
- {
- cChar = rMissingCodes.iterateCodePoints( &nStrIndex );
- bCached = rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &aFontName );
- if( !bCached || (rFontSelData.maSearchName != aFontName) )
- pRemainingCodes[ nRemainingLength++ ] = cChar;
- }
- rMissingCodes = OUString( pRemainingCodes, nRemainingLength );
- }
- else
- {
- OUString aOldMissingCodes = rMissingCodes;
- // call the hook to query the best matching glyph fallback font
- if( mpFallbackHook->FindFontSubstitute( rFontSelData, rMissingCodes ) )
- // apply outdev3.cxx specific fontname normalization
- GetEnglishSearchFontName( rFontSelData.maSearchName );
- else
- rFontSelData.maSearchName = "";
-
- // See fdo#32665 for an example. FreeSerif that has glyphs in normal
- // font, but not in the italic or bold version
- bool bSubSetOfFontRequiresPropertyFaking = rFontSelData.mbEmbolden || rFontSelData.maItalicMatrix != ItalicMatrix();
-
- // Cache the result even if there was no match, unless its from part of a font for which the properties need
- // to be faked. We need to rework this cache to take into account that fontconfig can return different fonts
- // for different input sizes, weights, etc. Basically the cache is way to naive
- if (!bSubSetOfFontRequiresPropertyFaking)
- {
- for(;;)
- {
- if( !rFontSelData.mpFontEntry->GetFallbackForUnicode( cChar, rFontSelData.GetWeight(), &rFontSelData.maSearchName ) )
- rFontSelData.mpFontEntry->AddFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName );
- if( nStrIndex >= aOldMissingCodes.getLength() )
- break;
- cChar = aOldMissingCodes.iterateCodePoints( &nStrIndex );
- }
- if( !rFontSelData.maSearchName.isEmpty() )
- {
- // remove cache entries that were still not resolved
- for( nStrIndex = 0; nStrIndex < rMissingCodes.getLength(); )
- {
- cChar = rMissingCodes.iterateCodePoints( &nStrIndex );
- rFontSelData.mpFontEntry->IgnoreFallbackForUnicode( cChar, rFontSelData.GetWeight(), rFontSelData.maSearchName );
- }
- }
- }
- }
-
- // find the matching device font
- if( !rFontSelData.maSearchName.isEmpty() )
- pFallbackData = FindFontFamily( rFontSelData.maSearchName );
- }
-
- // else find a matching font candidate for generic glyph fallback
- if( !pFallbackData )
- {
- // initialize font candidates for generic glyph fallback if needed
- if( mnFallbackCount < 0 )
- InitGenericGlyphFallback();
- // TODO: adjust nFallbackLevel by number of levels resolved by the fallback hook
- if( nFallbackLevel < mnFallbackCount )
- pFallbackData = mpFallbackList[ nFallbackLevel ];
- }
-
- return pFallbackData;
-}
-
-void PhysicalFontCollection::Add( PhysicalFontFace* pNewData )
-{
- OUString aSearchName = pNewData->GetFamilyName();
- GetEnglishSearchFontName( aSearchName );
-
- PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.find( aSearchName );
- PhysicalFontFamily* pFoundData = NULL;
- if( it != maPhysicalFontFamilies.end() )
- pFoundData = (*it).second;
-
- if( !pFoundData )
- {
- pFoundData = new PhysicalFontFamily( aSearchName );
- maPhysicalFontFamilies[ aSearchName ] = pFoundData;
- }
-
- bool bKeepNewData = pFoundData->AddFontFace( pNewData );
-
- if( !bKeepNewData )
- delete pNewData;
-}
-
-// find the font from the normalized font family name
-PhysicalFontFamily* PhysicalFontCollection::ImplFindBySearchName( const OUString& rSearchName ) const
-{
-#ifdef DEBUG
- OUString aTempName = rSearchName;
- GetEnglishSearchFontName( aTempName );
- DBG_ASSERT( aTempName == rSearchName, "PhysicalFontCollection::ImplFindBySearchName() called with non-normalized name" );
-#endif
-
- PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.find( rSearchName );
- if( it == maPhysicalFontFamilies.end() )
- return NULL;
-
- PhysicalFontFamily* pFoundData = (*it).second;
- return pFoundData;
-}
-
-PhysicalFontFamily* PhysicalFontCollection::ImplFindByAliasName(const OUString& rSearchName,
- const OUString& rShortName) const
-{
- // short circuit for impossible font name alias
- if (rSearchName.isEmpty())
- return NULL;
-
- // short circuit if no alias names are available
- if (!mbMapNames)
- return NULL;
-
- // use the font's alias names to find the font
- // TODO: get rid of linear search
- PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.begin();
- while( it != maPhysicalFontFamilies.end() )
- {
- PhysicalFontFamily* pData = (*it).second;
- if( pData->maMapNames.isEmpty() )
- continue;
-
- // if one alias name matches we found a matching font
- OUString aTempName;
- sal_Int32 nIndex = 0;
- do
- {
- aTempName = GetNextFontToken( pData->maMapNames, nIndex );
- // Test, if the Font name match with one of the mapping names
- if ( (aTempName == rSearchName) || (aTempName == rShortName) )
- return pData;
- }
- while ( nIndex != -1 );
- }
-
- return NULL;
-}
-
-PhysicalFontFamily* PhysicalFontCollection::FindFontFamily( const OUString& rFontName ) const
-{
- // normalize the font family name and
- OUString aName = rFontName;
- GetEnglishSearchFontName( aName );
- PhysicalFontFamily* pFound = ImplFindBySearchName( aName );
- return pFound;
-}
-
-PhysicalFontFamily* PhysicalFontCollection::ImplFindByTokenNames(const OUString& rTokenStr) const
-{
- PhysicalFontFamily* pFoundData = NULL;
-
- // use normalized font name tokens to find the font
- for( sal_Int32 nTokenPos = 0; nTokenPos != -1; )
- {
- OUString aSearchName = GetNextFontToken( rTokenStr, nTokenPos );
- if( aSearchName.isEmpty() )
- continue;
- GetEnglishSearchFontName( aSearchName );
- pFoundData = ImplFindBySearchName( aSearchName );
- if( pFoundData )
- break;
- }
-
- return pFoundData;
-}
-
-PhysicalFontFamily* PhysicalFontCollection::ImplFindBySubstFontAttr( const utl::FontNameAttr& rFontAttr ) const
-{
- PhysicalFontFamily* pFoundData = NULL;
-
- // use the font substitutions suggested by the FontNameAttr to find the font
- ::std::vector< OUString >::const_iterator it = rFontAttr.Substitutions.begin();
- for(; it != rFontAttr.Substitutions.end(); ++it )
- {
- OUString aSearchName( *it );
- GetEnglishSearchFontName( aSearchName );
-
- pFoundData = ImplFindBySearchName( aSearchName );
- if( pFoundData )
- return pFoundData;
- }
-
- // use known attributes from the configuration to find a matching substitute
- const sal_uLong nSearchType = rFontAttr.Type;
- if( nSearchType != 0 )
- {
- const FontWeight eSearchWeight = rFontAttr.Weight;
- const FontWidth eSearchWidth = rFontAttr.Width;
- const FontItalic eSearchSlant = ITALIC_DONTKNOW;
- const OUString aSearchName;
- pFoundData = ImplFindByAttributes( nSearchType,
- eSearchWeight, eSearchWidth, eSearchSlant, aSearchName );
- if( pFoundData )
- return pFoundData;
- }
-
- return NULL;
-}
-
-void PhysicalFontCollection::InitMatchData() const
-{
- // short circuit if already done
- if( mbMatchData )
- return;
- mbMatchData = true;
-
- // calculate MatchData for all entries
- const FontSubstConfiguration& rFontSubst = FontSubstConfiguration::get();
-
- PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.begin();
- for(; it != maPhysicalFontFamilies.end(); ++it )
- {
- const OUString& rSearchName = (*it).first;
- PhysicalFontFamily* pEntry = (*it).second;
-
- pEntry->InitMatchData( rFontSubst, rSearchName );
- }
-}
-
-PhysicalFontFamily* PhysicalFontCollection::ImplFindByAttributes( sal_uLong nSearchType,
- FontWeight eSearchWeight, FontWidth eSearchWidth,
- FontItalic eSearchItalic, const OUString& rSearchFamilyName ) const
-{
- if( (eSearchItalic != ITALIC_NONE) && (eSearchItalic != ITALIC_DONTKNOW) )
- nSearchType |= IMPL_FONT_ATTR_ITALIC;
-
- // don't bother to match attributes if the attributes aren't worth matching
- if( !nSearchType
- && ((eSearchWeight == WEIGHT_DONTKNOW) || (eSearchWeight == WEIGHT_NORMAL))
- && ((eSearchWidth == WIDTH_DONTKNOW) || (eSearchWidth == WIDTH_NORMAL)) )
- return NULL;
-
- InitMatchData();
- PhysicalFontFamily* pFoundData = NULL;
-
- long nTestMatch;
- long nBestMatch = 40000;
- sal_uLong nBestType = 0;
-
- PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.begin();
- for(; it != maPhysicalFontFamilies.end(); ++it )
- {
- PhysicalFontFamily* pData = (*it).second;
-
- // Get all information about the matching font
- sal_uLong nMatchType = pData->mnMatchType;
- FontWeight eMatchWeight= pData->meMatchWeight;
- FontWidth eMatchWidth = pData->meMatchWidth;
-
- // Calculate Match Value
- // 1000000000
- // 100000000
- // 10000000 CJK, CTL, None-Latin, Symbol
- // 1000000 FamilyName, Script, Fixed, -Special, -Decorative,
- // Titling, Capitals, Outline, Shadow
- // 100000 Match FamilyName, Serif, SansSerif, Italic,
- // Width, Weight
- // 10000 Scalable, Standard, Default,
- // full, Normal, Knownfont,
- // Otherstyle, +Special, +Decorative,
- // 1000 Typewriter, Rounded, Gothic, Schollbook
- // 100
- nTestMatch = 0;
-
- // test CJK script attributes
- if ( nSearchType & IMPL_FONT_ATTR_CJK )
- {
- // Matching language
- if( 0 == ((nSearchType ^ nMatchType) & IMPL_FONT_ATTR_CJK_ALLLANG) )
- nTestMatch += 10000000*3;
- if( nMatchType & IMPL_FONT_ATTR_CJK )
- nTestMatch += 10000000*2;
- if( nMatchType & IMPL_FONT_ATTR_FULL )
- nTestMatch += 10000000;
- }
- else if ( nMatchType & IMPL_FONT_ATTR_CJK )
- nTestMatch -= 10000000;
-
- // test CTL script attributes
- if( nSearchType & IMPL_FONT_ATTR_CTL )
- {
- if( nMatchType & IMPL_FONT_ATTR_CTL )
- nTestMatch += 10000000*2;
- if( nMatchType & IMPL_FONT_ATTR_FULL )
- nTestMatch += 10000000;
- }
- else if ( nMatchType & IMPL_FONT_ATTR_CTL )
- nTestMatch -= 10000000;
-
- // test LATIN script attributes
- if( nSearchType & IMPL_FONT_ATTR_NONELATIN )
- {
- if( nMatchType & IMPL_FONT_ATTR_NONELATIN )
- nTestMatch += 10000000*2;
- if( nMatchType & IMPL_FONT_ATTR_FULL )
- nTestMatch += 10000000;
- }
-
- // test SYMBOL attributes
- if ( nSearchType & IMPL_FONT_ATTR_SYMBOL )
- {
- const OUString& rSearchName = it->first;
- // prefer some special known symbol fonts
- if ( rSearchName.equalsAscii( "starsymbol" ) )
- nTestMatch += 10000000*6+(10000*3);
- else if ( rSearchName.equalsAscii( "opensymbol" ) )
- nTestMatch += 10000000*6;
- else if ( rSearchName.equalsAscii( "starbats" )
- || rSearchName.equalsAscii( "wingdings" )
- || rSearchName.equalsAscii( "monotypesorts" )
- || rSearchName.equalsAscii( "dingbats" )
- || rSearchName.equalsAscii( "zapfdingbats" ) )
- nTestMatch += 10000000*5;
- else if ( pData->mnTypeFaces & IMPL_DEVFONT_SYMBOL )
- nTestMatch += 10000000*4;
- else
- {
- if( nMatchType & IMPL_FONT_ATTR_SYMBOL )
- nTestMatch += 10000000*2;
- if( nMatchType & IMPL_FONT_ATTR_FULL )
- nTestMatch += 10000000;
- }
- }
- else if ( (pData->mnTypeFaces & (IMPL_DEVFONT_SYMBOL | IMPL_DEVFONT_NONESYMBOL)) == IMPL_DEVFONT_SYMBOL )
- nTestMatch -= 10000000;
- else if ( nMatchType & IMPL_FONT_ATTR_SYMBOL )
- nTestMatch -= 10000;
-
- // match stripped family name
- if( !rSearchFamilyName.isEmpty() && (rSearchFamilyName.equals(pData->maMatchFamilyName)) )
- nTestMatch += 1000000*3;
-
- // match ALLSCRIPT? attribute
- if( nSearchType & IMPL_FONT_ATTR_ALLSCRIPT )
- {
- if( nMatchType & IMPL_FONT_ATTR_ALLSCRIPT )
- nTestMatch += 1000000*2;
- if( nSearchType & IMPL_FONT_ATTR_ALLSUBSCRIPT )
- {
- if( 0 == ((nSearchType ^ nMatchType) & IMPL_FONT_ATTR_ALLSUBSCRIPT) )
- nTestMatch += 1000000*2;
- if( 0 != ((nSearchType ^ nMatchType) & IMPL_FONT_ATTR_BRUSHSCRIPT) )
- nTestMatch -= 1000000;
- }
- }
- else if( nMatchType & IMPL_FONT_ATTR_ALLSCRIPT )
- nTestMatch -= 1000000;
-
- // test MONOSPACE+TYPEWRITER attributes
- if( nSearchType & IMPL_FONT_ATTR_FIXED )
- {
- if( nMatchType & IMPL_FONT_ATTR_FIXED )
- nTestMatch += 1000000*2;
- // a typewriter attribute is even better
- if( 0 == ((nSearchType ^ nMatchType) & IMPL_FONT_ATTR_TYPEWRITER) )
- nTestMatch += 10000*2;
- }
- else if( nMatchType & IMPL_FONT_ATTR_FIXED )
- nTestMatch -= 1000000;
-
- // test SPECIAL attribute
- if( nSearchType & IMPL_FONT_ATTR_SPECIAL )
- {
- if( nMatchType & IMPL_FONT_ATTR_SPECIAL )
- nTestMatch += 10000;
- else if( !(nSearchType & IMPL_FONT_ATTR_ALLSERIFSTYLE) )
- {
- if( nMatchType & IMPL_FONT_ATTR_SERIF )
- nTestMatch += 1000*2;
- else if( nMatchType & IMPL_FONT_ATTR_SANSSERIF )
- nTestMatch += 1000;
- }
- }
- else if( (nMatchType & IMPL_FONT_ATTR_SPECIAL) && !(nSearchType & IMPL_FONT_ATTR_SYMBOL) )
- nTestMatch -= 1000000;
-
- // test DECORATIVE attribute
- if( nSearchType & IMPL_FONT_ATTR_DECORATIVE )
- {
- if( nMatchType & IMPL_FONT_ATTR_DECORATIVE )
- nTestMatch += 10000;
- else if( !(nSearchType & IMPL_FONT_ATTR_ALLSERIFSTYLE) )
- {
- if( nMatchType & IMPL_FONT_ATTR_SERIF )
- nTestMatch += 1000*2;
- else if ( nMatchType & IMPL_FONT_ATTR_SANSSERIF )
- nTestMatch += 1000;
- }
- }
- else if( nMatchType & IMPL_FONT_ATTR_DECORATIVE )
- nTestMatch -= 1000000;
-
- // test TITLE+CAPITALS attributes
- if( nSearchType & (IMPL_FONT_ATTR_TITLING | IMPL_FONT_ATTR_CAPITALS) )
- {
- if( nMatchType & (IMPL_FONT_ATTR_TITLING | IMPL_FONT_ATTR_CAPITALS) )
- nTestMatch += 1000000*2;
- if( 0 == ((nSearchType^nMatchType) & (IMPL_FONT_ATTR_TITLING | IMPL_FONT_ATTR_CAPITALS)))
- nTestMatch += 1000000;
- else if( (nMatchType & (IMPL_FONT_ATTR_TITLING | IMPL_FONT_ATTR_CAPITALS))
- && (nMatchType & (IMPL_FONT_ATTR_STANDARD | IMPL_FONT_ATTR_DEFAULT)) )
- nTestMatch += 1000000;
- }
- else if( nMatchType & (IMPL_FONT_ATTR_TITLING | IMPL_FONT_ATTR_CAPITALS) )
- nTestMatch -= 1000000;
-
- // test OUTLINE+SHADOW attributes
- if( nSearchType & (IMPL_FONT_ATTR_OUTLINE | IMPL_FONT_ATTR_SHADOW) )
- {
- if( nMatchType & (IMPL_FONT_ATTR_OUTLINE | IMPL_FONT_ATTR_SHADOW) )
- nTestMatch += 1000000*2;
- if( 0 == ((nSearchType ^ nMatchType) & (IMPL_FONT_ATTR_OUTLINE | IMPL_FONT_ATTR_SHADOW)) )
- nTestMatch += 1000000;
- else if( (nMatchType & (IMPL_FONT_ATTR_OUTLINE | IMPL_FONT_ATTR_SHADOW))
- && (nMatchType & (IMPL_FONT_ATTR_STANDARD | IMPL_FONT_ATTR_DEFAULT)) )
- nTestMatch += 1000000;
- }
- else if ( nMatchType & (IMPL_FONT_ATTR_OUTLINE | IMPL_FONT_ATTR_SHADOW) )
- nTestMatch -= 1000000;
-
- // test font name substrings
- // TODO: calculate name matching score using e.g. Levenstein distance
- if( (rSearchFamilyName.getLength() >= 4) && (pData->maMatchFamilyName.getLength() >= 4)
- && ((rSearchFamilyName.indexOf( pData->maMatchFamilyName ) != -1)
- || (pData->maMatchFamilyName.indexOf( rSearchFamilyName ) != -1)) )
- nTestMatch += 5000;
-
- // test SERIF attribute
- if( nSearchType & IMPL_FONT_ATTR_SERIF )
- {
- if( nMatchType & IMPL_FONT_ATTR_SERIF )
- nTestMatch += 1000000*2;
- else if( nMatchType & IMPL_FONT_ATTR_SANSSERIF )
- nTestMatch -= 1000000;
- }
-
- // test SANSERIF attribute
- if( nSearchType & IMPL_FONT_ATTR_SANSSERIF )
- {
- if( nMatchType & IMPL_FONT_ATTR_SANSSERIF )
- nTestMatch += 1000000;
- else if ( nMatchType & IMPL_FONT_ATTR_SERIF )
- nTestMatch -= 1000000;
- }
-
- // test ITALIC attribute
- if( nSearchType & IMPL_FONT_ATTR_ITALIC )
- {
- if( pData->mnTypeFaces & IMPL_DEVFONT_ITALIC )
- nTestMatch += 1000000*3;
- if( nMatchType & IMPL_FONT_ATTR_ITALIC )
- nTestMatch += 1000000;
- }
- else if( !(nSearchType & IMPL_FONT_ATTR_ALLSCRIPT)
- && ((nMatchType & IMPL_FONT_ATTR_ITALIC)
- || !(pData->mnTypeFaces & IMPL_DEVFONT_NONEITALIC)) )
- nTestMatch -= 1000000*2;
-
- // test WIDTH attribute
- if( (eSearchWidth != WIDTH_DONTKNOW) && (eSearchWidth != WIDTH_NORMAL) )
- {
- if( eSearchWidth < WIDTH_NORMAL )
- {
- if( eSearchWidth == eMatchWidth )
- nTestMatch += 1000000*3;
- else if( (eMatchWidth < WIDTH_NORMAL) && (eMatchWidth != WIDTH_DONTKNOW) )
- nTestMatch += 1000000;
- }
- else
- {
- if( eSearchWidth == eMatchWidth )
- nTestMatch += 1000000*3;
- else if( eMatchWidth > WIDTH_NORMAL )
- nTestMatch += 1000000;
- }
- }
- else if( (eMatchWidth != WIDTH_DONTKNOW) && (eMatchWidth != WIDTH_NORMAL) )
- nTestMatch -= 1000000;
-
- // test WEIGHT attribute
- if( (eSearchWeight != WEIGHT_DONTKNOW) && (eSearchWeight != WEIGHT_NORMAL) && (eSearchWeight != WEIGHT_MEDIUM) )
- {
- if( eSearchWeight < WEIGHT_NORMAL )
- {
- if( pData->mnTypeFaces & IMPL_DEVFONT_LIGHT )
- nTestMatch += 1000000;
- if( (eMatchWeight < WEIGHT_NORMAL) && (eMatchWeight != WEIGHT_DONTKNOW) )
- nTestMatch += 1000000;
- }
- else
- {
- if( pData->mnTypeFaces & IMPL_DEVFONT_BOLD )
- nTestMatch += 1000000;
- if( eMatchWeight > WEIGHT_BOLD )
- nTestMatch += 1000000;
- }
- }
- else if( ((eMatchWeight != WEIGHT_DONTKNOW) && (eMatchWeight != WEIGHT_NORMAL) && (eMatchWeight != WEIGHT_MEDIUM))
- || !(pData->mnTypeFaces & IMPL_DEVFONT_NORMAL) )
- nTestMatch -= 1000000;
-
- // prefer scalable fonts
- if( pData->mnTypeFaces & IMPL_DEVFONT_SCALABLE )
- nTestMatch += 10000*4;
- else
- nTestMatch -= 10000*4;
-
- // test STANDARD+DEFAULT+FULL+NORMAL attributes
- if( nMatchType & IMPL_FONT_ATTR_STANDARD )
- nTestMatch += 10000*2;
- if( nMatchType & IMPL_FONT_ATTR_DEFAULT )
- nTestMatch += 10000;
- if( nMatchType & IMPL_FONT_ATTR_FULL )
- nTestMatch += 10000;
- if( nMatchType & IMPL_FONT_ATTR_NORMAL )
- nTestMatch += 10000;
-
- // test OTHERSTYLE attribute
- if( ((nSearchType ^ nMatchType) & IMPL_FONT_ATTR_OTHERSTYLE) != 0 )
- {
- nTestMatch -= 10000;
- }
-
- // test ROUNDED attribute
- if( 0 == ((nSearchType ^ nMatchType) & IMPL_FONT_ATTR_ROUNDED) )
- nTestMatch += 1000;
-
- // test TYPEWRITER attribute
- if( 0 == ((nSearchType ^ nMatchType) & IMPL_FONT_ATTR_TYPEWRITER) )
- nTestMatch += 1000;
-
- // test GOTHIC attribute
- if( nSearchType & IMPL_FONT_ATTR_GOTHIC )
- {
- if( nMatchType & IMPL_FONT_ATTR_GOTHIC )
- nTestMatch += 1000*3;
- if( nMatchType & IMPL_FONT_ATTR_SANSSERIF )
- nTestMatch += 1000*2;
- }
-
- // test SCHOOLBOOK attribute
- if( nSearchType & IMPL_FONT_ATTR_SCHOOLBOOK )
- {
- if( nMatchType & IMPL_FONT_ATTR_SCHOOLBOOK )
- nTestMatch += 1000*3;
- if( nMatchType & IMPL_FONT_ATTR_SERIF )
- nTestMatch += 1000*2;
- }
-
- // compare with best matching font yet
- if ( nTestMatch > nBestMatch )
- {
- pFoundData = pData;
- nBestMatch = nTestMatch;
- nBestType = nMatchType;
- }
- else if( nTestMatch == nBestMatch )
- {
- // some fonts are more suitable defaults
- if( nMatchType & IMPL_FONT_ATTR_DEFAULT )
- {
- pFoundData = pData;
- nBestType = nMatchType;
- }
- else if( (nMatchType & IMPL_FONT_ATTR_STANDARD) &&
- !(nBestType & IMPL_FONT_ATTR_DEFAULT) )
- {
- pFoundData = pData;
- nBestType = nMatchType;
- }
- }
- }
-
- return pFoundData;
-}
-
-PhysicalFontFamily* PhysicalFontCollection::FindDefaultFont() const
-{
- // try to find one of the default fonts of the
- // UNICODE, SANSSERIF, SERIF or FIXED default font lists
- const DefaultFontConfiguration& rDefaults = DefaultFontConfiguration::get();
- LanguageTag aLanguageTag( OUString( "en"));
- OUString aFontname = rDefaults.getDefaultFont( aLanguageTag, DEFAULTFONT_SANS_UNICODE );
- PhysicalFontFamily* pFoundData = ImplFindByTokenNames( aFontname );
- if( pFoundData )
- return pFoundData;
-
- aFontname = rDefaults.getDefaultFont( aLanguageTag, DEFAULTFONT_SANS );
- pFoundData = ImplFindByTokenNames( aFontname );
- if( pFoundData )
- return pFoundData;
-
- aFontname = rDefaults.getDefaultFont( aLanguageTag, DEFAULTFONT_SERIF );
- pFoundData = ImplFindByTokenNames( aFontname );
- if( pFoundData )
- return pFoundData;
-
- aFontname = rDefaults.getDefaultFont( aLanguageTag, DEFAULTFONT_FIXED );
- pFoundData = ImplFindByTokenNames( aFontname );
- if( pFoundData )
- return pFoundData;
-
- // now try to find a reasonable non-symbol font
-
- InitMatchData();
-
- PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.begin();
- for(; it != maPhysicalFontFamilies.end(); ++it )
- {
- PhysicalFontFamily* pData = (*it).second;
- if( pData->mnMatchType & IMPL_FONT_ATTR_SYMBOL )
- continue;
- pFoundData = pData;
- if( pData->mnMatchType & (IMPL_FONT_ATTR_DEFAULT|IMPL_FONT_ATTR_STANDARD) )
- break;
- }
- if( pFoundData )
- return pFoundData;
-
- // finding any font is better than finding no font at all
- it = maPhysicalFontFamilies.begin();
- if( it != maPhysicalFontFamilies.end() )
- pFoundData = (*it).second;
-
- return pFoundData;
-}
-
-PhysicalFontCollection* PhysicalFontCollection::Clone( bool bScalable, bool bEmbeddable ) const
-{
- PhysicalFontCollection* pClonedCollection = new PhysicalFontCollection;
- pClonedCollection->mbMapNames = mbMapNames;
- pClonedCollection->mpPreMatchHook = mpPreMatchHook;
- pClonedCollection->mpFallbackHook = mpFallbackHook;
-
- // TODO: clone the config-font attributes too?
- pClonedCollection->mbMatchData = false;
-
- PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.begin();
- for(; it != maPhysicalFontFamilies.end(); ++it )
- {
- const PhysicalFontFamily* pFontFace = (*it).second;
- pFontFace->UpdateCloneFontList( *pClonedCollection, bScalable, bEmbeddable );
- }
-
- return pClonedCollection;
-}
-
-ImplGetDevFontList* PhysicalFontCollection::GetDevFontList() const
-{
- ImplGetDevFontList* pGetDevFontList = new ImplGetDevFontList;
-
- PhysicalFontFamilies::const_iterator it = maPhysicalFontFamilies.begin();
- for(; it != maPhysicalFontFamilies.end(); ++it )
- {
- const PhysicalFontFamily* pFontFamily = (*it).second;
- pFontFamily->UpdateDevFontList( *pGetDevFontList );
- }
-
- return pGetDevFontList;
-}
-
-ImplGetDevSizeList* PhysicalFontCollection::GetDevSizeList( const OUString& rFontName ) const
-{
- ImplGetDevSizeList* pGetDevSizeList = new ImplGetDevSizeList( rFontName );
-
- PhysicalFontFamily* pFontFamily = FindFontFamily( rFontName );
- if( pFontFamily != NULL )
- {
- std::set<int> rHeights;
- pFontFamily->GetFontHeights( rHeights );
-
- std::set<int>::const_iterator it = rHeights.begin();
- for(; it != rHeights.begin(); ++it )
- pGetDevSizeList->Add( *it );
- }
-
- return pGetDevSizeList;
-}
FontSelectPatternAttributes::FontSelectPatternAttributes( const Font& rFont,
const OUString& rSearchName, const Size& rSize, float fExactHeight )
@@ -2128,355 +1021,6 @@ ImplFontEntry* ImplFontCache::GetFontEntry( PhysicalFontCollection* pFontList,
return pEntry;
}
-namespace
-{
- OUString stripCharSetFromName(const OUString& _aName)
- {
- // I worry that someone will have a font which *does* have
- // e.g. "Greek" legitimately at the end of its name :-(
- const char*suffixes[] =
- {
- " baltic",
- " ce",
- " cyr",
- " greek",
- " tur",
- " (arabic)",
- " (hebrew)",
- " (thai)",
- " (vietnamese)"
- };
-
- OUString aName = _aName;
- // These can be crazily piled up, e.g. Times New Roman CYR Greek
- bool bFinished = false;
- while (!bFinished)
- {
- bFinished = true;
- for (size_t i = 0; i < SAL_N_ELEMENTS(suffixes); ++i)
- {
- size_t nLen = strlen(suffixes[i]);
- if (aName.endsWithIgnoreAsciiCaseAsciiL(suffixes[i], nLen))
- {
- bFinished = false;
- aName = aName.copy(0, aName.getLength() - nLen);
- }
- }
- }
- return aName;
- }
-}
-
-PhysicalFontFamily* PhysicalFontCollection::ImplFindByFont( FontSelectPattern& rFSD ) const
-{
- // give up if no fonts are available
- if( !Count() )
- return NULL;
-
- bool bMultiToken = false;
- sal_Int32 nTokenPos = 0;
- OUString& aSearchName = rFSD.maSearchName; // TODO: get rid of reference
- for(;;)
- {
- rFSD.maTargetName = GetNextFontToken( rFSD.GetFamilyName(), nTokenPos );
- aSearchName = rFSD.maTargetName;
-
-#if ENABLE_GRAPHITE
- // Until features are properly supported, they are appended to the
- // font name, so we need to strip them off so the font is found.
- sal_Int32 nFeat = aSearchName.indexOf(grutils::GrFeatureParser::FEAT_PREFIX);
- OUString aOrigName = rFSD.maTargetName;
- OUString aBaseFontName = aSearchName.copy( 0, (nFeat != -1) ? nFeat : aSearchName.getLength() );
- if (nFeat != -1 &&
- -1 != aSearchName.indexOf(grutils::GrFeatureParser::FEAT_ID_VALUE_SEPARATOR, nFeat))
- {
- aSearchName = aBaseFontName;
- rFSD.maTargetName = aBaseFontName;
- }
-
-#endif
-
- GetEnglishSearchFontName( aSearchName );
- ImplFontSubstitute( aSearchName );
- // #114999# special emboldening for Ricoh fonts
- // TODO: smarter check for special cases by using PreMatch infrastructure?
- if( (rFSD.GetWeight() > WEIGHT_MEDIUM)
- && aSearchName.startsWithIgnoreAsciiCase( "hg" ) )
- {
- OUString aBoldName;
- if( aSearchName.startsWithIgnoreAsciiCase( "hggothicb" ) )
- aBoldName = "hggothice";
- else if( aSearchName.startsWithIgnoreAsciiCase( "hgpgothicb" ) )
- aBoldName = "hgpgothice";
- else if( aSearchName.startsWithIgnoreAsciiCase( "hgminchol" ) )
- aBoldName = "hgminchob";
- else if( aSearchName.startsWithIgnoreAsciiCase( "hgpminchol" ) )
- aBoldName = "hgpminchob";
- else if( aSearchName.equalsIgnoreAsciiCase( "hgminchob" ) )
- aBoldName = "hgminchoe";
- else if( aSearchName.equalsIgnoreAsciiCase( "hgpminchob" ) )
- aBoldName = "hgpminchoe";
-
- if( !aBoldName.isEmpty() && ImplFindBySearchName( aBoldName ) )
- {
- // the other font is available => use it
- aSearchName = aBoldName;
- // prevent synthetic emboldening of bold version
- rFSD.SetWeight(WEIGHT_DONTKNOW);
- }
- }
-
-#if ENABLE_GRAPHITE
- // restore the features to make the font selection data unique
- rFSD.maTargetName = aOrigName;
-#endif
- // check if the current font name token or its substitute is valid
- PhysicalFontFamily* pFoundData = ImplFindBySearchName( aSearchName );
- if( pFoundData )
- return pFoundData;
-
- // some systems provide special customization
- // e.g. they suggest "serif" as UI-font, but this name cannot be used directly
- // because the system wants to map it to another font first, e.g. "Helvetica"
-#if ENABLE_GRAPHITE
- // use the target name to search in the prematch hook
- rFSD.maTargetName = aBaseFontName;
-#endif
-
- // Related: fdo#49271 RTF files often contain weird-ass
- // Win 3.1/Win95 style fontnames which attempt to put the
- // charset encoding into the filename
- // http://www.webcenter.ru/~kazarn/eng/fonts_ttf.htm
- OUString sStrippedName = stripCharSetFromName(rFSD.maTargetName);
- if (!sStrippedName.equals(rFSD.maTargetName))
- {
- rFSD.maTargetName = sStrippedName;
- aSearchName = rFSD.maTargetName;
- GetEnglishSearchFontName(aSearchName);
- pFoundData = ImplFindBySearchName(aSearchName);
- if( pFoundData )
- return pFoundData;
- }
-
- if( mpPreMatchHook )
- {
- if( mpPreMatchHook->FindFontSubstitute( rFSD ) )
- GetEnglishSearchFontName( aSearchName );
- }
-#if ENABLE_GRAPHITE
- // the prematch hook uses the target name to search, but we now need
- // to restore the features to make the font selection data unique
- rFSD.maTargetName = aOrigName;
-#endif
- pFoundData = ImplFindBySearchName( aSearchName );
- if( pFoundData )
- return pFoundData;
-
- // break after last font name token was checked unsuccessfully
- if( nTokenPos == -1)
- break;
- bMultiToken = true;
- }
-
- // if the first font was not available find the next available font in
- // the semicolon separated list of font names. A font is also considered
- // available when there is a matching entry in the Tools->Options->Fonts
- // dialog witho neither ALWAYS nor SCREENONLY flags set and the substitution
- // font is available
- for( nTokenPos = 0; nTokenPos != -1; )
- {
- if( bMultiToken )
- {
- rFSD.maTargetName = GetNextFontToken( rFSD.GetFamilyName(), nTokenPos );
- aSearchName = rFSD.maTargetName;
- GetEnglishSearchFontName( aSearchName );
- }
- else
- nTokenPos = -1;
- if( mpPreMatchHook )
- if( mpPreMatchHook->FindFontSubstitute( rFSD ) )
- GetEnglishSearchFontName( aSearchName );
- ImplFontSubstitute( aSearchName );
- PhysicalFontFamily* pFoundData = ImplFindBySearchName( aSearchName );
- if( pFoundData )
- return pFoundData;
- }
-
- // if no font with a directly matching name is available use the
- // first font name token and get its attributes to find a replacement
- if ( bMultiToken )
- {
- nTokenPos = 0;
- rFSD.maTargetName = GetNextFontToken( rFSD.GetFamilyName(), nTokenPos );
- aSearchName = rFSD.maTargetName;
- GetEnglishSearchFontName( aSearchName );
- }
-
- OUString aSearchShortName;
- OUString aSearchFamilyName;
- FontWeight eSearchWeight = rFSD.GetWeight();
- FontWidth eSearchWidth = rFSD.GetWidthType();
- sal_uLong nSearchType = 0;
- FontSubstConfiguration::getMapName( aSearchName, aSearchShortName, aSearchFamilyName,
- eSearchWeight, eSearchWidth, nSearchType );
-
- // note: the search name was already translated to english (if possible)
- // use the font's shortened name if needed
- if ( aSearchShortName != aSearchName )
- {
- PhysicalFontFamily* pFoundData = ImplFindBySearchName( aSearchShortName );
- if( pFoundData )
- {
-#ifdef UNX
- /* #96738# don't use mincho as an replacement for "MS Mincho" on X11: Mincho is
- a korean bitmap font that is not suitable here. Use the font replacement table,
- that automatically leads to the desired "HG Mincho Light J". Same story for
- MS Gothic, there are thai and korean "Gothic" fonts, so we even prefer Andale */
- static OUString aMS_Mincho( "msmincho" );
- static OUString aMS_Gothic( "msgothic" );
- if ((aSearchName != aMS_Mincho) && (aSearchName != aMS_Gothic))
- // TODO: add heuristic to only throw out the fake ms* fonts
-#endif
- {
- return pFoundData;
- }
- }
- }
-
- // use font fallback
- const FontNameAttr* pFontAttr = NULL;
- if( !aSearchName.isEmpty() )
- {
- // get fallback info using FontSubstConfiguration and
- // the target name, it's shortened name and family name in that order
- const FontSubstConfiguration& rFontSubst = FontSubstConfiguration::get();
- pFontAttr = rFontSubst.getSubstInfo( aSearchName );
- if ( !pFontAttr && (aSearchShortName != aSearchName) )
- pFontAttr = rFontSubst.getSubstInfo( aSearchShortName );
- if ( !pFontAttr && (aSearchFamilyName != aSearchShortName) )
- pFontAttr = rFontSubst.getSubstInfo( aSearchFamilyName );
-
- // try the font substitutions suggested by the fallback info
- if( pFontAttr )
- {
- PhysicalFontFamily* pFoundData = ImplFindBySubstFontAttr( *pFontAttr );
- if( pFoundData )
- return pFoundData;
- }
- }
-
- // if a target symbol font is not available use a default symbol font
- if( rFSD.IsSymbolFont() )
- {
- LanguageTag aDefaultLanguageTag( OUString( "en"));
- aSearchName = DefaultFontConfiguration::get().getDefaultFont( aDefaultLanguageTag, DEFAULTFONT_SYMBOL );
- PhysicalFontFamily* pFoundData = ImplFindByTokenNames( aSearchName );
- if( pFoundData )
- return pFoundData;
- }
-
- // now try the other font name tokens
- while( nTokenPos != -1 )
- {
- rFSD.maTargetName = GetNextFontToken( rFSD.GetFamilyName(), nTokenPos );
- if( rFSD.maTargetName.isEmpty() )
- continue;
-
- aSearchName = rFSD.maTargetName;
- GetEnglishSearchFontName( aSearchName );
-
- OUString aTempShortName;
- OUString aTempFamilyName;
- sal_uLong nTempType = 0;
- FontWeight eTempWeight = rFSD.GetWeight();
- FontWidth eTempWidth = WIDTH_DONTKNOW;
- FontSubstConfiguration::getMapName( aSearchName, aTempShortName, aTempFamilyName,
- eTempWeight, eTempWidth, nTempType );
-
- // use a shortend token name if available
- if( aTempShortName != aSearchName )
- {
- PhysicalFontFamily* pFoundData = ImplFindBySearchName( aTempShortName );
- if( pFoundData )
- return pFoundData;
- }
-
- // use a font name from font fallback list to determine font attributes
- // get fallback info using FontSubstConfiguration and
- // the target name, it's shortened name and family name in that order
- const FontSubstConfiguration& rFontSubst = FontSubstConfiguration::get();
- const FontNameAttr* pTempFontAttr = rFontSubst.getSubstInfo( aSearchName );
- if ( !pTempFontAttr && (aTempShortName != aSearchName) )
- pTempFontAttr = rFontSubst.getSubstInfo( aTempShortName );
- if ( !pTempFontAttr && (aTempFamilyName != aTempShortName) )
- pTempFontAttr = rFontSubst.getSubstInfo( aTempFamilyName );
-
- // try the font substitutions suggested by the fallback info
- if( pTempFontAttr )
- {
- PhysicalFontFamily* pFoundData = ImplFindBySubstFontAttr( *pTempFontAttr );
- if( pFoundData )
- return pFoundData;
- if( !pFontAttr )
- pFontAttr = pTempFontAttr;
- }
- }
-
- // if still needed use the alias names of the installed fonts
- if( mbMapNames )
- {
- PhysicalFontFamily* pFoundData = ImplFindByAliasName( rFSD.maTargetName, aSearchShortName );
- if( pFoundData )
- return pFoundData;
- }
-
- // if still needed use the font request's attributes to find a good match
- if (MsLangId::isSimplifiedChinese(rFSD.meLanguage))
- nSearchType |= IMPL_FONT_ATTR_CJK | IMPL_FONT_ATTR_CJK_SC;
- else if (MsLangId::isTraditionalChinese(rFSD.meLanguage))
- nSearchType |= IMPL_FONT_ATTR_CJK | IMPL_FONT_ATTR_CJK_TC;
- else if (MsLangId::isKorean(rFSD.meLanguage))
- nSearchType |= IMPL_FONT_ATTR_CJK | IMPL_FONT_ATTR_CJK_KR;
- else if (rFSD.meLanguage == LANGUAGE_JAPANESE)
- nSearchType |= IMPL_FONT_ATTR_CJK | IMPL_FONT_ATTR_CJK_JP;
- else
- {
- nSearchType |= ImplIsCJKFont( rFSD.GetFamilyName() );
- if( rFSD.IsSymbolFont() )
- nSearchType |= IMPL_FONT_ATTR_SYMBOL;
- }
-
- ImplCalcType( nSearchType, eSearchWeight, eSearchWidth, rFSD.GetFamilyType(), pFontAttr );
- PhysicalFontFamily* pFoundData = ImplFindByAttributes( nSearchType,
- eSearchWeight, eSearchWidth, rFSD.GetSlant(), aSearchFamilyName );
-
- if( pFoundData )
- {
- // overwrite font selection attributes using info from the typeface flags
- if( (eSearchWeight >= WEIGHT_BOLD)
- && (eSearchWeight > rFSD.GetWeight())
- && (pFoundData->mnTypeFaces & IMPL_DEVFONT_BOLD) )
- rFSD.SetWeight( eSearchWeight );
- else if( (eSearchWeight < WEIGHT_NORMAL)
- && (eSearchWeight < rFSD.GetWeight())
- && (eSearchWeight != WEIGHT_DONTKNOW)
- && (pFoundData->mnTypeFaces & IMPL_DEVFONT_LIGHT) )
- rFSD.SetWeight( eSearchWeight );
-
- if( (nSearchType & IMPL_FONT_ATTR_ITALIC)
- && ((rFSD.GetSlant() == ITALIC_DONTKNOW) || (rFSD.GetSlant() == ITALIC_NONE))
- && (pFoundData->mnTypeFaces & IMPL_DEVFONT_ITALIC) )
- rFSD.SetItalic( ITALIC_NORMAL );
- }
- else
- {
- // if still needed fall back to default fonts
- pFoundData = FindDefaultFont();
- }
-
- return pFoundData;
-}
-
ImplFontEntry* ImplFontCache::GetGlyphFallbackFont( PhysicalFontCollection* pFontCollection,
FontSelectPattern& rFontSelData, int nFallbackLevel, OUString& rMissingCodes )
{
diff --git a/vcl/source/gdi/print.cxx b/vcl/source/gdi/print.cxx
index a33ba8766cd8..dca6ef3ee5e2 100644
--- a/vcl/source/gdi/print.cxx
+++ b/vcl/source/gdi/print.cxx
@@ -43,6 +43,7 @@
#include <svids.hrc>
#include <jobset.h>
#include <outdev.h>
+#include "PhysicalFontCollection.hxx"
#include <print.h>
#include <comphelper/processfactory.hxx>
diff --git a/vcl/source/gdi/virdev.cxx b/vcl/source/gdi/virdev.cxx
index 3ef75cf9261e..cf8ab485212e 100644
--- a/vcl/source/gdi/virdev.cxx
+++ b/vcl/source/gdi/virdev.cxx
@@ -30,6 +30,7 @@
#include <salframe.hxx>
#include <salvd.hxx>
#include <outdev.h>
+#include "PhysicalFontCollection.hxx"
#include <svdata.hxx>
using namespace ::com::sun::star::uno;
diff --git a/vcl/source/window/window.cxx b/vcl/source/window/window.cxx
index 7ba83e77c294..f56c2e1f821f 100644
--- a/vcl/source/window/window.cxx
+++ b/vcl/source/window/window.cxx
@@ -68,6 +68,7 @@
#include "window.h"
#include "toolbox.h"
#include "outdev.h"
+#include "PhysicalFontCollection.hxx"
#include "brdwin.hxx"
#include "helpwin.hxx"
#include "sallayout.hxx"
diff --git a/vcl/unx/generic/gdi/salgdi3.cxx b/vcl/unx/generic/gdi/salgdi3.cxx
index 389db5df6d9e..109c95af68e9 100644
--- a/vcl/unx/generic/gdi/salgdi3.cxx
+++ b/vcl/unx/generic/gdi/salgdi3.cxx
@@ -50,6 +50,7 @@
#include "generic/printergfx.hxx"
#include "impfont.hxx"
#include "outdev.h"
+#include "PhysicalFontCollection.hxx"
#include "PhysicalFontFace.hxx"
#include "salframe.hxx"
#include "unx/saldata.hxx"
diff --git a/vcl/win/source/gdi/salgdi3.cxx b/vcl/win/source/gdi/salgdi3.cxx
index e56e6423941c..c88cc5882c8f 100644
--- a/vcl/win/source/gdi/salgdi3.cxx
+++ b/vcl/win/source/gdi/salgdi3.cxx
@@ -43,6 +43,7 @@
#include "fontsubset.hxx"
#include "outdev.h"
+#include "PhysicalFontCollection.hxx"
#include "PhysicalFontFace.hxx"
#include "sft.hxx"
#include "win/saldata.hxx"