1
#region PDFsharp - A .NET library for processing PDF
4
// Stefan Lange (mailto:Stefan.Lange@pdfsharp.com)
6
// Copyright (c) 2005-2009 empira Software GmbH, Cologne (Germany)
8
// http://www.pdfsharp.com
9
// http://sourceforge.net/projects/pdfsharp
11
// Permission is hereby granted, free of charge, to any person obtaining a
12
// copy of this software and associated documentation files (the "Software"),
13
// to deal in the Software without restriction, including without limitation
14
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
15
// and/or sell copies of the Software, and to permit persons to whom the
16
// Software is furnished to do so, subject to the following conditions:
18
// The above copyright notice and this permission notice shall be included
19
// in all copies or substantial portions of the Software.
21
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27
// DEALINGS IN THE SOFTWARE.
31
using System.Diagnostics;
32
using System.Runtime.InteropServices;
33
using System.ComponentModel;
37
using System.Drawing.Drawing2D;
41
using System.Windows.Media;
43
using PdfSharp.Internal;
44
using PdfSharp.Fonts.OpenType;
46
using PdfSharp.Pdf.Advanced;
48
namespace PdfSharp.Drawing
51
/// Temporary hack to implement PrivateFontCollection.
55
public XTypefaceHack(string typefaceName)
56
: this(typefaceName, XFontStyle.Regular, XFontWeights.Normal, new XFontStretch())
59
public XTypefaceHack(string typefaceName, XFontStyle style, XFontWeight weight)
60
: this(typefaceName, style, weight, new XFontStretch())
63
public XTypefaceHack(string fontFamilyName, XFontStyle style, XFontWeight weight, XFontStretch stretch)
65
if (String.IsNullOrEmpty(fontFamilyName))
66
throw new ArgumentNullException("fontFamilyName");
68
this.fontFamilyName = fontFamilyName;
71
this.stretch = stretch;
74
public string FontFamilyName
76
get { return this.fontFamilyName; }
78
string fontFamilyName;
80
public XFontWeight Weight
82
get { return this.weight; }
84
private XFontWeight weight;
86
public XFontStyle Style
88
get { return this.style; }
90
private XFontStyle style;
92
public XFontStretch Stretch
94
get { return this.stretch; }
96
private XFontStretch stretch;
103
internal class XTypeface
106
// /// Construct a typeface
108
// /// <param name="typefaceName">font typeface name</param>
110
// string typefaceName
112
// // assume face name is family name until we get face name resolved properly.
114
// new FontFamily(typefaceName),
115
// FontStyles.Normal,
116
// FontWeights.Normal,
117
// FontStretches.Normal
124
// /// Construct a typeface
126
// /// <param name="fontFamily">Font family</param>
127
// /// <param name="style">Font style</param>
128
// /// <param name="weight">Boldness of font</param>
129
// /// <param name="stretch">Width of characters</param>
131
// FontFamily fontFamily,
133
// FontWeight weight,
134
// FontStretch stretch
141
// FontFamily.FontFamilyGlobalUI
148
// /// Construct a typeface
150
// /// <param name="fontFamily">Font family</param>
151
// /// <param name="style">Font style</param>
152
// /// <param name="weight">Boldness of font</param>
153
// /// <param name="stretch">Width of characters</param>
154
// /// <param name="fallbackFontFamily">fallback font family</param>
156
// FontFamily fontFamily,
158
// FontWeight weight,
159
// FontStretch stretch,
160
// FontFamily fallbackFontFamily
163
// if (fontFamily == null)
165
// throw new ArgumentNullException("fontFamily");
168
// _fontFamily = fontFamily;
171
// _stretch = stretch;
172
// _fallbackFontFamily = fallbackFontFamily;
178
// private FontFamily _fontFamily;
180
// // these _style, _weight and _stretch are only used for storing what was passed into the constructor.
181
// // Since FontFamily may change these values when it includes a style name implicitly,
182
// private FontStyle _style;
183
// private FontWeight _weight;
184
// private FontStretch _stretch;
190
// public FontFamily FontFamily
192
// get { return _fontFamily; }
197
// /// Font weight (light, bold, etc.)
199
// public FontWeight Weight
201
// get { return _weight; }
206
// /// Font style (italic, oblique)
208
// public FontStyle Style
210
// get { return _style; }
215
// /// Font Stretch (narrow, wide, etc.)
217
// public FontStretch Stretch
219
// get { return _stretch; }
225
// private FontFamily _fallbackFontFamily;
227
// // Cached canonical values of the typeface.
228
// private CachedTypeface _cachedTypeface;
232
// /// Returns true if FontStyle.Oblique is algorithmically simulated by
233
// /// slanting glyphs. Returns false otherwise.
235
// public bool IsObliqueSimulated
239
// return (CachedTypeface.TypefaceMetrics.StyleSimulations & StyleSimulations.ItalicSimulation) != 0;
244
// /// Returns true if FontStyle.Bold is algorithmically simulated by
245
// /// thickening glyphs. Returns false otherwise.
247
// public bool IsBoldSimulated
251
// return (CachedTypeface.TypefaceMetrics.StyleSimulations & StyleSimulations.BoldSimulation) != 0;
256
// /// Obtain a glyph typeface that corresponds to the Typeface object constructed from an OpenType font family.
257
// /// If the Typeface was constructed from a composite font family, returns null.
259
// /// <param name="glyphTypeface">GlyphTypeface object that corresponds to this Typeface, or null if the Typeface
260
// /// was constructed from a composite font.</param>
261
// /// <returns>Whether glyphTypeface is not null.</returns>
262
// public bool TryGetGlyphTypeface(out GlyphTypeface glyphTypeface)
264
// glyphTypeface = CachedTypeface.TypefaceMetrics as GlyphTypeface;
265
// return glyphTypeface != null;
270
// /// Fallback font family
272
// internal FontFamily FallbackFontFamily
274
// get { return _fallbackFontFamily; }
278
// /// (Western) x-height relative to em size.
280
// public double XHeight
284
// return CachedTypeface.TypefaceMetrics.XHeight;
290
// /// Distance from baseline to top of English capital, relative to em size.
292
// public double CapsHeight
296
// return CachedTypeface.TypefaceMetrics.CapsHeight;
302
// /// Distance from baseline to underline position
304
// public double UnderlinePosition
308
// return CachedTypeface.TypefaceMetrics.UnderlinePosition;
314
// /// Underline thickness
316
// public double UnderlineThickness
320
// return CachedTypeface.TypefaceMetrics.UnderlineThickness;
326
// /// Distance from baseline to strike-through position
328
// public double StrikethroughPosition
332
// return CachedTypeface.TypefaceMetrics.StrikethroughPosition;
338
// /// strike-through thickness
340
// public double StrikethroughThickness
344
// return CachedTypeface.TypefaceMetrics.StrikethroughThickness;
349
// /// Collection of culture-dependant face names.
351
// public LanguageSpecificStringDictionary FaceNames
355
// return new LanguageSpecificStringDictionary(CachedTypeface.TypefaceMetrics.AdjustedFaceNames);
360
// /// Distance from character cell top to English baseline relative to em size.
362
// internal double Baseline
366
// return CachedTypeface.FirstFontFamily.Baseline;
371
// /// Baseline to baseline distance relative to em size
373
// internal double LineSpacing
377
// return CachedTypeface.FirstFontFamily.LineSpacing;
382
// /// Flag indicating if the typeface is of symbol type
384
// internal bool Symbol
388
// return CachedTypeface.TypefaceMetrics.Symbol;
392
// internal bool NullFont
396
// return CachedTypeface.NullFont;
400
// // Tries to get a GlyphTypeface based on the Typeface properties. The
401
// // return value can be null. However, if CheckFastPathNominalGlyphs
402
// // returns true, then one can expect this function to return a valid
403
// // GlyphTypeface that maps all the specified text.
404
// internal GlyphTypeface TryGetGlyphTypeface()
406
// return CachedTypeface.TypefaceMetrics as GlyphTypeface;
409
// internal FontStyle CanonicalStyle
413
// return CachedTypeface.CanonicalStyle;
417
// internal FontWeight CanonicalWeight
421
// return CachedTypeface.CanonicalWeight;
425
// internal FontStretch CanonicalStretch
429
// return CachedTypeface.CanonicalStretch;
435
// /// Scan through specified character string checking for valid character
436
// /// nominal glyph.
438
// /// <param name="charBufferRange">character buffer range</param>
439
// /// <param name="emSize">height of Em</param>
440
// /// <param name="widthMax">maximum width allowed</param>
441
// /// <param name="keepAWord">do not stop arbitrarily in the middle of a word</param>
442
// /// <param name="numberSubstitution">digits require complex shaping</param>
443
// /// <param name="cultureInfo">CultureInfo of the text</param>
444
// /// <param name="stringLengthFit">number of character fit in given width</param>
445
// /// <returns>whether the specified string can be optimized by nominal glyph lookup</returns>
446
// internal bool CheckFastPathNominalGlyphs(
447
// CharacterBufferRange charBufferRange,
451
// bool numberSubstitution,
452
// CultureInfo cultureInfo,
453
// out int stringLengthFit
456
// stringLengthFit = 0;
458
// if (CachedTypeface.NullFont) return false;
460
// GlyphTypeface glyphTypeface = TryGetGlyphTypeface();
462
// if (glyphTypeface == null) return false;
465
// stringLengthFit = 0;
466
// IDictionary<int, ushort> cmap = glyphTypeface.CharacterToGlyphMap;
468
// double totalWidth = 0;
471
// ushort blankGlyph = glyphTypeface.BlankGlyphIndex;
472
// ushort glyph = blankGlyph;
474
// ushort charFlagsMask = numberSubstitution ?
475
// (ushort)(CharacterAttributeFlags.CharacterComplex | CharacterAttributeFlags.CharacterDigit) :
476
// (ushort)CharacterAttributeFlags.CharacterComplex;
477
// ushort charFlags = 0;
478
// ushort charFastTextCheck = (ushort)(CharacterAttributeFlags.CharacterFastText | CharacterAttributeFlags.CharacterIdeo);
480
// bool symbolTypeface = glyphTypeface.Symbol;
481
// if (symbolTypeface)
483
// // we don't care what code points are present if it's a non-Unicode font such as Symbol or Wingdings;
484
// // the code points don't have any standardized meanings, and we always want to bypass shaping
485
// charFlagsMask = 0;
492
// char ch = charBufferRange[i++];
493
// int charClass = (int)Classification.GetUnicodeClassUTF16(ch);
494
// charFlags = Classification.CharAttributeOf(charClass).Flags;
495
// charFastTextCheck &= charFlags;
496
// cmap.TryGetValue(ch, out glyph);
498
// totalWidth += emSize * glyphTypeface.GetAdvanceWidth(glyph);
501
// i < charBufferRange.Length
502
// && ((charFlags & charFlagsMask) == 0)
503
// && (glyph != 0 || symbolTypeface)
504
// && glyph != blankGlyph
507
// // i is now at a character immediately following a leading blank
511
// i < charBufferRange.Length
512
// && totalWidth <= widthMax
513
// && ((charFlags & charFlagsMask) == 0)
514
// && (glyph != 0 || symbolTypeface)
517
// char ch = charBufferRange[i++];
518
// int charClass = (int)Classification.GetUnicodeClassUTF16(ch);
519
// charFlags = Classification.CharAttributeOf(charClass).Flags;
520
// charFastTextCheck &= charFlags;
521
// cmap.TryGetValue(ch, out glyph);
522
// totalWidth += emSize * glyphTypeface.GetAdvanceWidth(glyph);
525
// if (symbolTypeface)
527
// // always optimize for non-Unicode font as we don't support shaping or typographic features;
528
// // we also don't fall back from non-Unicode fonts so we don't care if there are missing glyphs
529
// stringLengthFit = i;
535
// // character is not supported by the font
539
// if ((charFlags & charFlagsMask) != 0)
541
// // complex character encountered, exclude it
542
// Debug.Assert(i > 0);
546
// // first char is complex, fail the call
551
// stringLengthFit = i;
552
// TypographyAvailabilities typography = glyphTypeface.FontFaceLayoutInfo.TypographyAvailabilities;
554
// if ((charFastTextCheck & (byte)CharacterAttributeFlags.CharacterFastText) != 0)
556
// // all input code points are Fast Text
558
// (TypographyAvailabilities.FastTextTypographyAvailable
559
// | TypographyAvailabilities.FastTextMajorLanguageLocalizedFormAvailable
564
// // Considered too risky to optimize. It is either because the font
565
// // has required features or the font has 'locl' lookup for major languages.
568
// else if ((typography & TypographyAvailabilities.FastTextExtraLanguageLocalizedFormAvailable) != 0)
570
// // The font has 'locl' lookup for FastText code points for non major languages.
571
// // Check whether the input is major langauge. If it is, we are still good to optimize.
572
// return MajorLanguages.Contains(cultureInfo);
576
// // No FastText flags are present, safe to optimize
580
// else if ((charFastTextCheck & (byte)CharacterAttributeFlags.CharacterIdeo) != 0)
582
// // The input are all ideographs, check the IdeoTypographyAvailable bit. It is safe if
583
// // the bit is not set.
584
// return ((typography & TypographyAvailabilities.IdeoTypographyAvailable) == 0);
588
// // for all the rest of the cases, just check whether there is any required typography
589
// // present at all. If none exists, it is optimizable. We might under-optimize here but
590
// // it will be non-major languages.
591
// return ((typography & TypographyAvailabilities.Available) == 0);
597
// /// Lookup characters nominal glyphs and width
599
// /// <param name="charBufferRange">character buffer range</param>
600
// /// <param name="emSize">height of Em</param>
601
// /// <param name="toIdeal"> scaling factor from real to ideal unit </param>
602
// /// <param name="nominalWidths">glyph nominal advances in ideal units</param>
603
// /// <param name="idealWidth">total width in ideal units</param>
604
// /// <returns>true for success</returns>
605
// /// <remarks>This function is only used in fast path, and can only be called
606
// /// if CheckFastPathNominalGlyphs has previously returned true.</remarks>
607
// internal void GetCharacterNominalWidthsAndIdealWidth(
608
// CharacterBufferRange charBufferRange,
611
// out int[] nominalWidths,
612
// out int idealWidth
615
// // This function should only be called if CheckFastPathNominalGlyphs has
616
// // returned true so we can assume the ITypefaceMetrics is a GlyphTypeface.
617
// GlyphTypeface glyphTypeface = TryGetGlyphTypeface();
618
// Invariant.Assert(glyphTypeface != null);
620
// IDictionary<int, ushort> cmap = glyphTypeface.CharacterToGlyphMap;
621
// nominalWidths = new int[charBufferRange.Length];
624
// for (int i = 0; i < charBufferRange.Length; i++)
626
// ushort glyphIndex;
627
// cmap.TryGetValue(charBufferRange[i], out glyphIndex);
628
// double advance = emSize * glyphTypeface.GetAdvanceWidth(glyphIndex);
630
// nominalWidths[i] = (int)Math.Round(advance * toIdeal);
631
// idealWidth += nominalWidths[i];
639
// /// Create correspondent hash code for the object
641
// /// <returns>object hash code</returns>
642
// public override int GetHashCode()
644
// int hash = _fontFamily.GetHashCode();
646
// if (_fallbackFontFamily != null)
647
// hash = HashFn.HashMultiply(hash) + _fallbackFontFamily.GetHashCode();
649
// hash = HashFn.HashMultiply(hash) + _style.GetHashCode();
650
// hash = HashFn.HashMultiply(hash) + _weight.GetHashCode();
651
// hash = HashFn.HashMultiply(hash) + _stretch.GetHashCode();
652
// return HashFn.HashScramble(hash);
658
// /// Equality check
660
// public override bool Equals(object o)
662
// Typeface t = o as Typeface;
666
// return _style == t._style
667
// && _weight == t._weight
668
// && _stretch == t._stretch
669
// && _fontFamily.Equals(t._fontFamily)
670
// && CompareFallbackFontFamily(t._fallbackFontFamily);
674
// internal bool CompareFallbackFontFamily(FontFamily fallbackFontFamily)
676
// if (fallbackFontFamily == null || _fallbackFontFamily == null)
677
// return fallbackFontFamily == _fallbackFontFamily;
679
// return _fallbackFontFamily.Equals(fallbackFontFamily);
682
// //----------------------------------------
684
// //----------------------------------------
685
// private CachedTypeface CachedTypeface
689
// if (_cachedTypeface == null)
691
// CachedTypeface cachedTypeface = TypefaceMetricsCache.ReadonlyLookup(this) as CachedTypeface;
693
// if (cachedTypeface == null)
695
// cachedTypeface = ConstructCachedTypeface();
696
// TypefaceMetricsCache.Add(this, cachedTypeface);
699
// // For thread-safety, set the _cachedTypeface field only after we have a fully
700
// // initialized CachedTypeface object.
701
// _cachedTypeface = cachedTypeface;
704
// return _cachedTypeface;
708
// private CachedTypeface ConstructCachedTypeface()
710
// FontStyle canonicalStyle = _style;
711
// FontWeight canonicalWeight = _weight;
712
// FontStretch canonicalStretch = _stretch;
715
// // We always call FontFamily.FindFirstFontFamilyAndFace() method to resolve the
716
// // canonical styles since the implied styles in FontFamily name will override
717
// // the given styles in the Typeface. But we don't always use the IFontFamily
718
// // instance returned from this method because an equal instance might already be
721
// FontFamily sourceFontFamily = FontFamily;
723
// IFontFamily firstFontFamily = sourceFontFamily.FindFirstFontFamilyAndFace(
724
// ref canonicalStyle,
725
// ref canonicalWeight,
726
// ref canonicalStretch
729
// if (firstFontFamily == null)
731
// if (FallbackFontFamily != null)
733
// sourceFontFamily = FallbackFontFamily;
734
// firstFontFamily = sourceFontFamily.FindFirstFontFamilyAndFace(
735
// ref canonicalStyle,
736
// ref canonicalWeight,
737
// ref canonicalStretch
741
// if (firstFontFamily == null)
743
// sourceFontFamily = null;
744
// firstFontFamily = FontFamily.LookupFontFamily(FontFamily.NullFontFamilyCanonicalName);
748
// // If it's a named font, map all occurrences of the same name to one cached IFontFamily.
749
// if (sourceFontFamily != null && sourceFontFamily.Source != null)
751
// // We lookup in the cache to see if there is cached IFontFamily instance of the source FontFamily. Otherwise,
752
// // this IFontFamily value is added to the TypefaceMetrics cache.
753
// IFontFamily cachedValue = TypefaceMetricsCache.ReadonlyLookup(sourceFontFamily.FamilyIdentifier) as IFontFamily;
755
// if (cachedValue != null)
757
// firstFontFamily = cachedValue;
761
// TypefaceMetricsCache.Add(sourceFontFamily.FamilyIdentifier, firstFontFamily);
765
// ITypefaceMetrics typefaceMetrics = firstFontFamily.GetTypefaceMetrics(canonicalStyle, canonicalWeight, canonicalStretch);
767
// return new CachedTypeface(
773
// sourceFontFamily == null