PDF에서 복사하거나 문서를 인쇄 할 때 텍스트 'fi'가 잘리는 이유는 무엇입니까?


15

포함 된 Adobe Reader PDF 파일에서 복사 할 때

Define an operation

나는 오히려 본다

Dene an operation

텍스트를 붙여 넣을 때 왜 그렇습니까?

이 성가신 문제를 어떻게 해결할 수 있습니까?

또한 Microsoft Office Word 파일을 프린터로 인쇄 할 때 과거에 이런 현상이 발생하는 것을 보았습니다.

답변:


13

글꼴 문제처럼 들립니다. PDF에서 아마도 단어에서 OpenType fi 합자 를 사용하고 define있으며 대상 응용 프로그램의 현재 글꼴에 해당 글리프가 없습니다.

Acrobat에서 합자를 복사하여 쉽게 분해 할 수있는 방법이 있는지 모르겠습니다.

인쇄 문제는 아마도 글꼴과 관련이 있습니다. 프린터가 문서의 글꼴을 자체 내장 글꼴로 대체하고 프린터의 글꼴 버전에 특정 글리프가 누락되었을 수 있습니다. 이 문제를 해결하려면 항상 글꼴을 프린터로 다운로드하도록 Windows에 지시해야합니다.

인쇄시 또 다른 가능성 : UniScribe가 활성화되지 않았을 수 있습니다. MS KB 2642020은이 문제와 가능한 해결 방법에 대해 설명합니다 (즉, EMF 형식 인쇄 대신 RAW 형식 인쇄 사용). 상황이 특정 문제와 약간 다르지만 원인이 같을 수 있으며 동일한 해결 방법이 적용될 수 있습니다.


1
합자에 관심이 있다면 어떻게 든 올바르게 작동하도록 구성 할 수 있는지 궁금합니다. 다른 PDF 리더가 어떻게 작동하는지 볼 수 있습니다. 글꼴을 프린터로 보내도록 정확히 어디에서 구성해야합니까?
Tamara Wijsman

1
앱의 인쇄 대화 상자에서 : 프린터의 Properties(또는 Preferences대화 버전에 따라)를 클릭하고 Layout또는 Quality탭 에 있는지 확인한 후 Advanced버튼을 클릭하십시오 . 에서 Graphic그룹의 변경 TrueType Font에 옵션을 Download as Softfont. 여기에는 Windows 기본 제공 대화 상자를 사용하는 대부분의 PostScript 프린터 및 프린터가 포함되지만 다른 드라이버로 인해 물건이 움직이거나 누락 될 수 있습니다.
afrazier

일부 용도의 MS KB 2642020을 찾을 수 있습니다. 해당 정보를 사용하여 답변을 편집했습니다.
afrazier

문제를 설명해 주셔서 감사합니다. 아직이 문제를 해결하려고 시도하지 않았지만 인쇄 문제가 다시 발생하면 반드시 시도하겠습니다. 두 솔루션 중 하나 가이 매우 특정한 문제를 해결할 것이라고 생각합니다 ... :)
Tamara Wijsman

@afrazier, 당신이 "응용 프로그램의 인쇄 대화 상자에서 :"를 시작으로 귀하의 의견에 쓴 솔루션이 저에게 효과적이었습니다. 그 텍스트를 답장에 넣는 것이 좋습니다. (나는 그것을 편집 할 수 있지만 결정은 당신에게 달려 있다고 생각합니다.)
Alan

9

이러한 "깨진"단어는 대부분 원본으로 바꿀 수 있습니다. 다음과 같은 경우 단어를 안전하게 바꿀 수 있습니다.

  • dene또는 같은 rey단어는 실제 단어가 아닙니다
  • 같은 definefirefly,이 을 다시 추가 합자 sequeneces에 대한 방법은 ( ff, fi, fl, ffi, 또는 ffl) 진짜 단어를 만들

대부분의 합자 문제는 이러한 기준에 적합합니다. 그러나 다음을 교체 할 수 없습니다.

  • us 원래 단어 였을 수도 있지만 실제 단어이기 때문에 fluffs
    • 또한 affirm, butterfly, fielders, fortifies, flimflam, misfits...
  • cus그것은 cuffs또는 될 수 있기 때문에ficus
    • 또한 stiffed/ stifled, rifle/ riffle, flung/ fluffing...

이 496 천 단어 영어 사전 ,가 16055 개 적어도 하나가 포함 된 단어 ff, fi, fl, ffi, 또는 ffl로 설정하는 15879 개 자신의 합자가 제거 될 때 단어. 173 과 같이 충돌 그 누락 단어 cuffsficus, 마지막 (3)는 그 사전의 단어가 포함되어 있기 때문이다 ff, fifl.

이 "합자 제거 된"단어 중 790 개 는 같은 실제 단어 us이지만 15089 는 깨진 단어입니다. 깨진 단어 중 14960 은 원래 단어로 안전하게 대체 될 수 있습니다. 즉, 깨진 단어의 99.1 % 는 수정 가능 하며 합자를 포함하는 원래 단어의 93.2 % 는 PDF를 복사하여 붙여 넣은 후에 복구 할 수 있습니다. 합자 시퀀스를 포함하는 단어의 6.8 % 가 충돌 ( cus) 및 하위 단어 ( us) 로 손실됩니다 . 보장되지 않은 각 단어에 대한 최상의 대체 방법을 선택하기 위해 어떤 방법 (단어 / 문서 컨텍스트?)을 선택하지 않는 한 바꿔 놓음.

아래는 위의 통계를 생성 한 Python 스크립트입니다. 한 줄에 한 단어로 된 사전 텍스트 파일이 필요합니다. 마지막으로 수정 가능한 깨진 단어를 원래 단어로 매핑하는 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를 동일한 링크에서 다시 업로드했습니다. 도움이 되길 바랍니다. 또한 코드 / 결과에 몇 가지 문제가 있음을 발견했습니다 (새 사전에는 단어에 마침표가 있고 비교하기 전에 단어를 소문자로 쓰지 않는 동안 마침표를 자리 표시 자로 사용). 나는 모든 교체가 정확하다고 생각하지만, 소금 한 덩어리로 가져 가면 더 좋은 교체가 가능하다는 것을 알고 있습니다. 정규식을 사용하여 교체를 자동화하는 것이 좋지만 각 교체가 자신의 눈에 맞는지 확인하십시오.
Jan Van Bruggen

7

여기의 문제는 다른 답변 과 마찬가지로 합자가 있습니다. 그러나 OpenType과는 전혀 관련이 없습니다. 근본적인 문제는 PDF는 내용과 의미에 거의 관심이 없지만 인쇄 될 페이지를 충실하게 표현하는 데 중점을 둔 사전 인쇄 형식이라는 것입니다.

텍스트는 텍스트가 아니라 특정 위치의 글꼴에서 문자 모양 으로 배치됩니다. 그래서 당신은»글리프 번호 72를 거기에, 글리프 번호 101을 거기에, 글리프 번호 108과 같은 곳에 놓습니다. ...«. 그 수준에서 기본적으로 텍스트의 아무 개념이없는 전혀 . 어떻게 보이는지에 대한 설명 일뿐 입니다. 여러 글리프에서 의미를 추출하는 데는 두 가지 문제점이 있습니다.

  1. 공간 레이아웃. PDF에는 이미 각 글리프를 배치 할 위치에 대한 특정 정보가 포함되어 있기 때문에 일반적인 텍스트처럼 기본 텍스트가 없습니다. 또 다른 부작용은 공백이 없다는 것입니다. 물론, 당신은 텍스트를 볼 수 있지만 PDF에는 없습니다. 전혀 아무것도 방출 할 수 없을 때 왜 빈 그림 문자를 방출합니까? 결국 결과는 같습니다. 따라서 PDF 리더는 텍스트를 신중하게 다시 작성하여 글리프 사이에 더 큰 간격이 생길 때마다 공백을 삽입해야합니다.

  2. PDF는 텍스트가 아닌 글리프를 렌더링합니다. 대부분의 경우 글리프 ID는 포함 된 글꼴의 유니 코드 코드 포인트 또는 최소한 ASCII 코드와 일치합니다. 이는 처음에 PDF를 만든 사람에 따라 ASCII 또는 Latin 1 텍스트를 충분히 다시 얻을 수 있음을 의미합니다. 프로세스의 모든 것을 깨뜨 립니다). 그러나 종종 ASCII 텍스트를 정확하게 얻을 수있는 PDF조차 ASCII가 아닌 모든 것을 엉망으로 만듭니다. 특히 레이아웃 단계 후에 합자 및 대체 글리프 포함하는 아랍어와 같은 복잡한 스크립트에서는 끔찍합니다. 즉, 아랍어 PDF에는 실제 텍스트가 거의 포함되지 않습니다.

두 번째 문제는 당신이 직면하는 것과 같습니다. 일반적인 범인은 LaTeX인데,이 글꼴은 출력을 달성하기 위해 238982375 개의 서로 다른 글꼴 (각각 256 개로 제한됨)을 사용합니다. 일반 텍스트, 수학 (둘 이상 사용) 등의 글꼴이 다르면 특히 메타 폰트가 거의 20 년 전에 유니 코드보다 오래 사용되므로 유니 코드 매핑이 없었기 때문에 작업이 매우 어려워집니다. 움라우트는 또한 문자에 겹쳐진 분음 부호로 렌더링됩니다. 예를 들어 PDF에서 복사 할 때»ä«대신»¨a«가 표시됩니다 (물론 검색 할 수도 없음).

PDF를 생성하는 응용 프로그램은 실제 텍스트를 메타 데이터로 포함하도록 선택할 수 있습니다. 그렇지 않은 경우 포함 된 글꼴을 처리하는 방법과 PDF 리더가 원본 텍스트를 다시 조각 할 수 있는지 여부를 고려해야합니다. 그러나»fi«가 공백으로 복사되거나 전혀 복사되지 않는 것은 일반적으로 LaTeX PDF의 표시입니다. XeLaTeX로 전환하여 1990 년대 문자 인코딩 및 글꼴 표준에 도달하기를 희망하면서 돌에 유니 코드 문자를 페인트하고 생산자에게 던져야합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.