2011-01-25 11 views
7

私はいくつかのXAMLの行をバインドしてFonts.SystemFontFamiliesthanks to Norris Cheng's excellent blog post)にバインドする方法を知っていますが、国際的なフォントファミリやその他のローマ字以外のフォントファミリを除外する方法を理解できません。私のユーザーは "モンゴルのBaiti"、 "Microsoftのウイグル"、さらには "Webdings"を必要としないでしょう。リストにあるときは、フォントを見つけるのが難しくなります。doWPF:Fonts.SystemFontFamiliesから非ローマ字フォントを除外する方法は?

SystemFontFamiliesから到達可能なオブジェクトには、非記号ローマ字アルファベットを他のものから分離するためのプロパティがありますか?

編集:私が使用したい情報は、Windows 7のフォントコントロールパネルの "Designed for"フィールドにあります。このフィールドのこの文字列は、ラテンアルファベットのアプリケーションに便利なフォントの「ラテン」、Wingdingsなどのフォントの「インターナショナル」フォント(「モンゴル語」は「モンゴル語」など)、「シンボル」の他の言語名を含みます。 「カテゴリ」フィールドは、「表示」フォントと「テキスト」フォントとを区別するのにも役立ちます。残念ながら、私はコードからこの情報を得る方法を見つけることができず、OpenType specのどこにあるのか把握することさえできません。私の推測では、OpenType script tagsまたはlanguage tagsが含まれています。

+0

フィルタリングは 'CollectionViewSource'の' Filter'イベントを行うことができますが、私はあなたがそれを知っていたと思います。私はFontFamilyがSymbolなどであるかどうかを知る方法を見たことがありません。あなたが何を思いつくのが面白いか –

+1

あなたはそれが*ロット*をより困難にするか、それはちょっとした不便さに過ぎないと確信していますか? "非ローマン"フォントを削除しても、まだ多くのフォントが存在します。面白い質問:+1。 –

+0

フォントがサポートしているスクリプトは、関連するフォントクラスでは使用できません。これは埋め込みフォントメタデータを介して一貫して利用できると確信しています。MSはWindows 7の既知のフォントのフォント解析を実行してフォントメタデータのDBを作成しただけではありませんか? –

答えて

1

私はあなたがそれを自分で提供することなくこの種の情報を見つけるつもりはないと思います。フォントの仕様自体はこの情報を提供していないので、運が悪いということです。あなたの最善の策は、あなたのエンドユーザにとって「容認できる」とみなすフォントのリストを決定することです。

+0

これは多分無関係な細部の時間を無駄にする私の許容が使い果たされた後、私がおそらく終わることになるルートです。しかし、私は情報がどこかにあることを知っているので、私にはバグがあります。私の編集した質問を見てください。 – McKenzieG1

+0

こんにちは..これは興味深い情報です。今私は好奇心が強いです。フォントに関するオプションの情報で、OpenType以外のフォーマットにも適用されるかどうかは疑問です。このような場合は、ネットを通って滑り落ちるイメージを描くことができます。ただ言って。 –

11

"Roman"として読み込み可能であるかどうかを明白に定義するフォントに明示的な情報はありません。

グリフ解析を使用して、フォントがカバーするUnicode範囲を確認することができます。これは、あなたがどの言語のフォントをカバーしているかの手がかりを与えることができます。ただし、これには問題があります。例:

  1. デフォルトのWindows 7フォントは "Segoe UI"です。あなたのスキームでは、これを「ローマ字」フォントと見なしますか?グリフ解析を実行しても、ラテン文字だけでなく、他のUnicode範囲もカバーしています。アラビア語、タイ語。さて、少なくともラテン文字をカバーするフォントを含めることはできますが、ラテン文字の範囲がポイント3のようにラテン文字として実際には読み込めない場合はどうしますか?
  2. "Mongolian Baiti"の例には、基本的なラテン語の範囲をカバーするグリフが含まれているため、 "ローマ字"のテキストのレンダリングに使用できます。
  3. Webdingsはラテン語の範囲をカバーしているため、解析を通ることはできますが、実際には読みやすいラテン文字は含まれていません。

おそらく狭いものにグリフ解析を適用することはできますが、誤検出が起こる可能性があります。

更新

私は自分のアプリケーションでフォントリストに対処する必要が、これだけでは、このいずれかを残すことができませんでした! :)

実際には、フォントがGlyphTypeface.Symbolプロパティ(私には新しさ)を介してシンボルフォントかどうかを派生させることができます。したがって、これと少しのグリフ解析では、以下の解決策が必要です。

しかし、これはラテン文字のためのグリフを持っているので、それはまだ "ロン"フォントであるので、 "モンゴルのBaiti"(とカリースタイルでは "Balti"ではなく "Baiti"あなたはこれを定義します。実際、私のシステム上のSymbol以外のフォントはすべて、少なくともラテン文字の範囲を持っているので、ラテンのグリフテストは実際にはどのフォントも除外しません。

"Mongolian Baiti"に対するあなたの特別な反対は何ですか?手動で管理されている除外リストを使わずに自動的に除外する予定はどうですか?

[Test] 
public void test() 
{ 
    var fonts = Fonts.SystemFontFamilies.OrderBy(x => x.ToString()); 

    var latinFonts = fonts.Where(f => 
     f.Source.StartsWith("Global") || 
     (!IsSymbol(f) && HasLatinGlyphs(f))); 

    latinFonts.ToList().ForEach(Console.WriteLine); 
} 

private bool IsSymbol(FontFamily fontFamily) 
{ 
    GlyphTypeface glyph = GetFirstGlpyhTypeface(fontFamily); 

    return glyph.Symbol; 
} 

private bool HasLatinGlyphs(FontFamily fontFamily) 
{ 
    GlyphTypeface glyph = GetFirstGlpyhTypeface(fontFamily); 

    for (int i = 32; i < 127; i++) 
    { 
     if (!glyph.CharacterToGlyphMap.ContainsKey(i)) return false; 
    } 

    return true; 
} 

private GlyphTypeface GetFirstGlpyhTypeface(FontFamily fontFamily) 
{ 
    Typeface typeface = fontFamily.GetTypefaces().First(); 

    GlyphTypeface glyph; 

    typeface.TryGetGlyphTypeface(out glyph); 

    return glyph; 
} 

アップデート2

あなたは、彼らがLatin Extended-ALatin Extended-B範囲のためのフィルタを含むことによって、拡張ラテン文字のために持っているもののサポートに基づいてフォントをフィルタリングで実験ができます。 Latin Extended-ALatin Extended-Bの両方でフィルタリングすると、ほとんどフォントが残っていませんが、Latin Extended-Aでフィルタリングするだけで、まだかなりのフォントが残っています。これはLatin-1Latin-1 Supplementのみをサポートしているため、Mongolian Baitiも自動的に削除されます。

このような分析が望ましい結果をもたらすかどうかは、非常に主観的です。 、再び、非常に主観的

private bool HasLatinGlyphs(FontFamily fontFamily) 
{ 
    GlyphTypeface glyph = GetFirstGlpyhTypeface(fontFamily); 

    List<Tuple<int, int>> ranges = new List<Tuple<int, int>> 
    { 
     new Tuple<int, int>(32, 126), //Latin-1 
     new Tuple<int, int>(160, 255), //Latin-1 Supplement 
     new Tuple<int, int>(256, 383), //Latin Extended-A 
     new Tuple<int, int>(384, 591), //Latin Extended-B 
    }; 

    foreach (Tuple<int, int> range in ranges) 
    { 
     for (int i = range.Item1; i <= range.Item2; i++) 
     { 
      if (!glyph.CharacterToGlyphMap.ContainsKey(i)) return false; 
     } 
    } 

    return true; 
} 

をが、以下は、ラテン語のグリフをサポートするフォントプラス国際通貨文字のサブセットを提供します::何かはしかしで実験し

List<Tuple<int, int>> ranges = new List<Tuple<int, int>> 
{ 
    new Tuple<int, int>(32, 126),  //Latin-1 
    new Tuple<int, int>(0x20A0, 0x20B5), //Currency Symbols (Partial) 
}; 

アップデートを3

あなたの質問には、Windows 7で動作するバージョンがあります。Windows 7の非表示フォント機能(@Rick Sladkeyで指摘されているように)を活用しています。デフォルトでは、現在のユーザーのロケール設定に役立つことが理想です。また、シンボルフォントを除外します:

[Test] 
public void test() 
{ 
    var allFonts = Fonts.SystemFontFamilies.OrderBy(x => x.Source); 

    var filteredFonts = allFonts.Where(f => 
     IsComposite(f) || (!IsSymbol(f) && !IsHidden(f))); 

    filteredFonts.ToList().ForEach(Console.WriteLine); 
} 

private static bool IsComposite(FontFamily fontFamily) 
{ 
    return fontFamily.Source.StartsWith("Global"); 
} 

private static bool IsSymbol(FontFamily fontFamily) 
{ 
    Typeface typeface = fontFamily.GetTypefaces().First(); 
    GlyphTypeface glyph; 
    typeface.TryGetGlyphTypeface(out glyph); 
    return glyph.Symbol; 
} 

private static bool IsHidden(FontFamily fontFamily) 
{ 
    const string Key = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Font Management"; 
    const string Value = "Inactive Fonts"; 
    RegistryKey key = Registry.CurrentUser.OpenSubKey(Key); 
    IEnumerable<string> hiddenFonts = (string[])key.GetValue(Value); 
    return hiddenFonts.Contains(fontFamily.Source); 
} 
+0

+1、非常に印象的な答え! –

+0

すてきな回答ありがとう! –

1

私はこれを行う簡単で信頼性の高い方法を見つけることができませんでした。私は、Windows 7で提供されているフォントの非表示状態を尊重するのが最善の解決策だと考えています。この方法では、ユーザーは適切なフォントを表示/非表示できます。残念ながら、フォントが隠されているかどうかを調べるためのAPIはありませんが、レジストリ設定を使用することはできます。ここで

はそれを行う方法について説明します記事です:

関連する問題