PDFからコピーしたり、ドキュメントを印刷したりすると、テキスト「fi」がカットされるのはなぜですか?


15

を含むAdobe Reader PDFファイルからコピーする場合

Define an operation

むしろ見る

Dene an operation

テキストを貼り付けるとき、なぜこれですか?

この迷惑な問題をどのように解決できますか?

これは、過去にMicrosoft Office Wordファイルをプリンターに印刷したときにも発生しました。

回答:


13

これはフォントの問題のようです。PDFは、おそらくWord でOpenType fi 合字を使用しておりdefine、宛先アプリケーションの現在のフォントにはそのグリフがありません。

Acrobatでコピー時に合字を分解する簡単な方法があるかどうかはわかりません。

印刷に関する問題も、おそらくフォントに関連しています。おそらく、プリンターがドキュメントのフォントを独自の組み込みフォントに置き換えることを許可しているため、プリンターのバージョンのフォントにもその特定のグリフがありません。この問題を回避するには、常にプリンターにフォントをダウンロードするようにWindowsに指示する必要があります。

印刷時の別の可能性:UniScribeが有効になっていない可能性があります。 MS KB 2642020は、これといくつかの考えられる回避策(つまり、EMFタイプの印刷ではなくRAWタイプの印刷を使用する)について説明しています。コンテキストは特定の問題とわずかに異なりますが、原因は同じであり、同じ回避策が適用される場合があります。


1
合字について興味深いのですが、どういうわけか適切に動作するように構成できるのでしょうか。おそらく、他のPDFリーダーの動作を見ることができたでしょう。フォントがプリンタに送信されるように、どこで正確に設定しますか?
タマラWijsman

1
アプリの印刷ダイアログから:プリンターのProperties(またはPreferencesダイアログのバージョンに応じて)をクリックし、タブLayoutまたはQualityタブにいることを確認して、Advancedボタンをクリックします。ではGraphicグループ、変更TrueType FontするオプションをDownload as Softfont。これは、ほとんどのPostScriptプリンターとWindowsの組み込みダイアログを使用するプリンターを対象としていますが、他のドライバーでは、物事が移動したり、なくなったりする場合があります。
フレイジャー

MS KB 2642020が使用されている場合があります。その情報を使用して回答を編集しました。
フレイジャー

問題を説明してくれてありがとう。私はまだこれを解決しようとしませんでしたが、もう一度印刷の問題が発生したときに必ず試してみます。両方の解決策のいずれかがこの非常に具体的な問題を確実に解決すると思います... :)
タマラWijsman

@afrazier、「アプリの印刷ダイアログから:」で始まるコメントで書いたソリューションが私にとってはうまくいきました。そのテキストを答えに入れることをお勧めします。(編集できますが、決定はあなた次第だと思います。)
アラン

9

これらの「壊れた」単語のほとんどをオリジナルに置き換えることができます。次の場合、単語を安全に置き換えることができます。

  • deneまたはのようにrey、それは本当の言葉ではありません
  • 同様definefirefly、そこにある1つの再追加の結紮sequenecesへの道は(fffiflffi、またはffl)と実際の単語を作ります

ほとんどの合字の問題はこれらの基準に適合します。ただし、次のものを置き換えることはできません。

  • us もともとあったかもしれないが、それは本当の言葉だから fluffs
    • またaffirmbutterflyfieldersfortifiesflimflammisfits...
  • cusどちらcuffsかになる可能性があるためficus
    • また、stiffed/ stifledrifle/ riffleflung/ fluffing...

では、この496千語英語辞書、ある16055個の少なくとも一つ含む単語fffiflffi、またはfflに変わり、15879の彼らの合字が削除されたときの言葉が。173のように衝突し、それらの行方不明の単語cuffsficus、最後の3は、その辞書は単語が含まれているためですfffifl

これらの「合字が削除された」単語のうち790は、などの実際の単語ですusが、15089は壊れた単語です。14960個の壊れた単語は元の単語に安全に置き換えることができます。つまり、壊れた単語の99.1%修正可能で、合字を含む元の単語の93.2%がPDFのコピーと貼り付け後に復元できます。合字シーケンスを含む単語の6.8%は、何らかの方法(単語/ドキュメントコンテキスト?)を選択して、保証されていない単語ごとに最適な置換を選択しない限り、衝突(cus)およびサブ単語(us)で失われます。置換。

以下は、上記の統計を生成した私のPythonスクリプトです。1行に1ワードの辞書テキストファイルが必要です。最後に、修正可能な壊れた単語を元の単語にマッピングするCSVファイルを書き込みます。

CSVをダウンロードするためのリンクを次に示します。http : //www.filedropper.com/brokenligaturewordfixes このマッピングを正規表現置換スクリプトのようなものと組み合わせて、破損した単語のほとんどを置換します。

import csv
import itertools
import operator
import re


dictionary_file_path = 'dictionary.txt'
broken_word_fixes_file_path = 'broken_word_fixes.csv'
ligatures = 'ffi', 'ffl', 'ff', 'fi', 'fl'


with open(dictionary_file_path, 'r') as dictionary_file:
    dictionary_words = list(set(line.strip()
                                for line in dictionary_file.readlines()))


broken_word_fixes = {}
ligature_words = set()
ligature_removed_words = set()
broken_words = set()
multi_ligature_words = set()


# Find broken word fixes for words with one ligature sequence
# Example: "dene" --> "define"
words_and_ligatures = list(itertools.product(dictionary_words, ligatures))
for i, (word, ligature) in enumerate(words_and_ligatures):
    if i % 50000 == 0:
        print('1-ligature words {percent:.3g}% complete'
              .format(percent=100 * i / len(words_and_ligatures)))
    for ligature_match in re.finditer(ligature, word):
        if word in ligature_words:
            multi_ligature_words.add(word)
        ligature_words.add(word)
        if word == ligature:
            break
        # Skip words that contain a larger ligature
        if (('ffi' in word and ligature != 'ffi') or
                ('ffl' in word and ligature != 'ffl')):
            break
        # Replace ligatures with dots to avoid creating new ligatures
        # Example: "offline" --> "of.ine" to avoid creating "fi"
        ligature_removed_word = (word[:ligature_match.start()] +
                                 '.' +
                                 word[ligature_match.end():])
        # Skip words that contain another ligature
        if any(ligature in ligature_removed_word for ligature in ligatures):
            continue
        ligature_removed_word = ligature_removed_word.replace('.', '')
        ligature_removed_words.add(ligature_removed_word)
        if ligature_removed_word not in dictionary_words:
            broken_word = ligature_removed_word
            broken_words.add(broken_word)
            if broken_word not in broken_word_fixes:
                broken_word_fixes[broken_word] = word
            else:
                # Ignore broken words with multiple possible fixes
                # Example: "cus" --> "cuffs" or "ficus"
                broken_word_fixes[broken_word] = None


# Find broken word fixes for word with multiple ligature sequences
# Example: "rey" --> "firefly"
multi_ligature_words = sorted(multi_ligature_words)
numbers_of_ligatures_in_word = 2, 3
for number_of_ligatures_in_word in numbers_of_ligatures_in_word:
    ligature_lists = itertools.combinations_with_replacement(
        ligatures, r=number_of_ligatures_in_word
    )
    words_and_ligature_lists = list(itertools.product(
        multi_ligature_words, ligature_lists
    ))
    for i, (word, ligature_list) in enumerate(words_and_ligature_lists):
        if i % 1000 == 0:
            print('{n}-ligature words {percent:.3g}% complete'
                  .format(n=number_of_ligatures_in_word,
                          percent=100 * i / len(words_and_ligature_lists)))
        # Skip words that contain a larger ligature
        if (('ffi' in word and 'ffi' not in ligature_list) or
                ('ffl' in word and 'ffl' not in ligature_list)):
            continue
        ligature_removed_word = word
        for ligature in ligature_list:
            ligature_matches = list(re.finditer(ligature, ligature_removed_word))
            if not ligature_matches:
                break
            ligature_match = ligature_matches[0]
            # Replace ligatures with dots to avoid creating new ligatures
            # Example: "offline" --> "of.ine" to avoid creating "fi"
            ligature_removed_word = (
                ligature_removed_word[:ligature_match.start()] +
                '.' +
                ligature_removed_word[ligature_match.end():]
            )
        else:
            # Skip words that contain another ligature
            if any(ligature in ligature_removed_word for ligature in ligatures):
                continue
            ligature_removed_word = ligature_removed_word.replace('.', '')
            ligature_removed_words.add(ligature_removed_word)
            if ligature_removed_word not in dictionary_words:
                broken_word = ligature_removed_word
                broken_words.add(broken_word)
                if broken_word not in broken_word_fixes:
                    broken_word_fixes[broken_word] = word
                else:
                    # Ignore broken words with multiple possible fixes
                    # Example: "ung" --> "flung" or "fluffing"
                    broken_word_fixes[broken_word] = None


# Remove broken words with multiple possible fixes
for broken_word, fixed_word in broken_word_fixes.copy().items():
    if not fixed_word:
        broken_word_fixes.pop(broken_word)


number_of_ligature_words = len(ligature_words)
number_of_ligature_removed_words = len(ligature_removed_words)
number_of_broken_words = len(broken_words)
number_of_fixable_broken_words = len(
    [word for word in set(broken_word_fixes.keys())
     if word and broken_word_fixes[word]]
)
number_of_recoverable_ligature_words = len(
    [word for word in set(broken_word_fixes.values())
     if word]
)
print(number_of_ligature_words, 'ligature words')
print(number_of_ligature_removed_words, 'ligature-removed words')
print(number_of_broken_words, 'broken words')
print(number_of_fixable_broken_words,
      'fixable broken words ({percent:.3g}% fixable)'
      .format(percent=(
      100 * number_of_fixable_broken_words / number_of_broken_words
  )))
print(number_of_recoverable_ligature_words,
      'recoverable ligature words ({percent:.3g}% recoverable)'
      '(for at least one broken word)'
      .format(percent=(
          100 * number_of_recoverable_ligature_words / number_of_ligature_words
      )))


with open(broken_word_fixes_file_path, 'w+', newline='') as broken_word_fixes_file:
    csv_writer = csv.writer(broken_word_fixes_file)
    sorted_broken_word_fixes = sorted(broken_word_fixes.items(),
                                      key=operator.itemgetter(0))
    for broken_word, fixed_word in sorted_broken_word_fixes:
        csv_writer.writerow([broken_word, fixed_word])

へのリンク.csvが壊れています。もう一度アップロードできるといいですね!いずれにせよ、コードをありがとう。
MagTun

@Enora同じリンクでCSVを再アップロードしました-それが役立つことを願っています!また、コード/結果にいくつかの問題があることに気付きました(新しいディクショナリには単語にピリオドがあり、単語を比較する前に単語を下げずに、ピリオドをプレースホルダーとして使用しています)私はすべての代替品が正しいと信じていますが、それらを一粒の塩と一緒に取り、より良い代替品が可能であることを知っています。置換を正規表現で自動化することをお勧めしますが、各置換が自分の目で良いことを確認します。
ヤンヴァンブルーゲン

7

ここでの問題は、他の回答ノートにあるように、合字に関するものです。ただし、OpenTypeとはまったく関係ありません。基本的な問題は、PDFは内容やセマンティクスにほとんど関わらず、印刷されるページを忠実に表現することを目的とした事前印刷形式であることです。

テキストはテキストとしてではなく、特定の位置のフォントからのグリフの連続としてレイアウトされます。したがって、「そこにグリフ番号72、そこにグリフ番号101、そこにグリフ番号108、...」を配置します。そのレベルでは基本的にテキストという概念が存在しないすべてで。それは単にそれどのように見えるかの説明です。一連のグリフから意味を抽出する際に2つの問題があります。

  1. 空間レイアウト。PDFには各グリフを配置する特定の情報が既に含まれているため、通常のように実際のテキストはその下にありません。もう1つの副作用は、スペースがないことです。もちろん、テキストを見るとPDFにはありません。まったく何も出力しないのに、なぜ空白のグリフを出力するのですか?結局、結果は同じです。そのため、PDFリーダーは、グリフの間に大きなギャップが発生するたびにスペースを挿入して、慎重にテキストを再びつなぎ合わせる必要があります。

  2. PDFはテキストではなくグリフをレンダリングします。ほとんどの場合、グリフIDはUnicodeコードポイントまたは少なくとも埋め込みフォントのASCIIコードに対応します。つまり、最初にPDFを作成した人(一部プロセスのすべてを文字化けします)。しかし、多くの場合、あなただけの罰金ASCIIテキストを取得することができさえPDFがあるすべてマングルうではない ASCIIを。特に、アラビア語のように合字と代替グリフのみを含む複雑なスクリプトの場合、レイアウト段階の後で恐ろしいことになります。つまり、アラビア語のPDFには実際のテキストがほとんど含まれないということです。

2番目の問題は、直面している問題のようなものです。ここでよくある原因はLaTeXで、推定数の238982375の異なるフォント(それぞれが256グリフに制限されています)を使用して出力を達成します。通常のテキスト、数学(複数を使用)などの異なるフォントは、特にMetafontがほぼ20年前にUnicodeに先行するため、Unicodeマッピングがなかったため、事態を非常に困難にします。ウムラウトは文字に分音記号を重ねることによってもレンダリングされます。たとえば、PDFからコピーすると»ä«ではなく»¨a«が表示されます(もちろん、検索もできません)。

PDFを作成するアプリケーションは、実際のテキストをメタデータとして含めることを選択できます。そうでない場合、埋め込まれたフォントの処理方法と、PDFリーダーが元のテキストを再びつなぎ合わせることができるかどうかに翻弄されます。しかし、»fi«が空白としてコピーされるか、まったくコピーされないことは、通常、LaTeX PDFのサインです。ユニコード文字を石にペイントしてプロデューサーに投げて、XeLaTeXに切り替えて、最終的に1990年代の文字エンコードとフォント標準に到達することを期待する必要があります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.