Bir PDF'den kopyaladığımda veya bir belge yazdırdığımda neden `` fi '' metni kesiliyor?


16

Şunları içeren bir Adobe Reader PDF dosyasından kopyaladığımda

Define an operation

Görmeyi tercih ederim

Dene an operation

metni yapıştırdığımda neden bu?

Bu sinir bozucu sorunu nasıl düzeltebilirim?

Ayrıca, yazıcım için bir Microsoft Office Word dosyası yazdırdığımda da bunun gerçekleştiğini gördüm.

Yanıtlar:


14

Bu bir yazı tipi sorunu gibi geliyor. PDF muhtemelen Word'de OpenType fi bağını kullanıyor defineve hedef uygulamanın geçerli yazı tipinde bu glif eksik.

Acrobat'ın kopyadaki ligatürü çözmesini sağlamanın kolay bir yolu olup olmadığını bilmiyorum.

Yazdırma ile ilgili sorunlarınız muhtemelen yazı tipiyle ilgilidir. Muhtemelen yazıcının belgenin yazı tipini kendi yerleşik yazı tipleriyle değiştirmesine izin veren bir şey vardır ve yazıcının yazı tipi sürümü de bu belirli glifi kaçırır. Windows'a bu soruna geçici bir çözüm bulmak için her zaman yazı tipini yazıcıya indirmesini söylemelisiniz.

Yazdırırken başka bir olasılık: UniScribe etkinleştirilmemiş olabilir. MS KB 2642020 bu ve bazı olası geçici çözümlerden bahseder (yani EMF türü yazdırma yerine RAW türü yazdırma kullanmak için). Bağlam özel sorununuzdan biraz farklı olsa da, neden aynı olabilir ve aynı geçici çözümler geçerli olabilir.


1
Bitişik harfler hakkında ilginç olan, bir şekilde düzgün davranacak şekilde yapılandırılıp yapılandırılamayacağını merak ediyorum. Belki diğer PDF okuyucuların nasıl davrandıklarına bakabilirim. Yazı tiplerini yazıcıya gönderilecek şekilde tam olarak nerede yapılandırırım?
Tamara Wijsman

1
Bir uygulamanın yazdırma iletişim kutusundan: Yazıcı için simgesini tıklayın Properties(veya Preferencesiletişim kutusu sürümüne bağlı olarak) Layoutveya Qualitysekmelerinde bulunduğunuzdan emin olun Advanceddüğmesini tıklayın. Gelen Graphicgrup değiştirmek TrueType Fontiçin seçeneği Download as Softfont. Bu, Windows yerleşik iletişim kutularını kullanan çoğu PostScript yazıcıyı ve yazıcıyı kapsar (sanırım), ancak diğer sürücülerde bazı şeyler hareket edebilir veya eksik olabilir.
afrazier

MS KB 2642020'yi bazı kullanımlar için bulabilirsiniz. Cevabımı bu bilgilerle düzenledim.
afrazier

Sorunu açıkladığınız için teşekkürler. Bunu henüz çözmeye çalışmadım, ancak bir yazdırma sorunuyla tekrar karşılaştığımda mutlaka deneyeceğim. Her iki çözümden birinin de bu çok özel sorunu çözeceğini sanırım ... :)
Tamara Wijsman

@afrazier, "Bir uygulamanın yazdırma iletişim kutusundan:" başlayarak yorumunuzda yazdığınız çözüm benim için çalıştı. Bu metni cevabınıza koymanızı öneririm. (Düzenleyebilirim, ama sanırım karar size kalmış.)
Alan

9

Bu "kırık" kelimelerin çoğunu orijinalleriyle değiştirebilirsiniz. Aşağıdaki durumlarda bir kelimeyi güvenle değiştirebilirsiniz:

  • gibi deneya da rey, gerçek bir kelime değil
  • gibi defineya fireflyvardır bir yeniden eklenti ligatür sequeneces yolu ( ff, fi, fl, ffi, veya ffl) ve gerçek bir sözcük yapmak

Ligatür problemlerinin çoğu bu kriterlere uygundur. Ancak, aşağıdakileri değiştiremezsiniz:

  • us çünkü gerçek bir kelime olsa da, aslında fluffs
    • Ayrıca affirm, butterfly, fielders, fortifies, flimflam, misfits...
  • cusçünkü cuffsyaficus
    • ayrıca stiffed/ stifled, rifle/ riffle, flung/ fluffing...

In bu 496 bin kelimelik İngilizce sözlükte vardır 16.055 en az bir içerirler kelimeler ff, fi, fl, ffi, veya ffl, dönüşür hangi 15.879 onların bitişik harfler kaldırıldığında kelimelerin. 173 gibi çarpıştı o kayıp kelimelerin cuffsve ficusve son 3 o sözlük kelimeleri içerdiğinden vardır ff, five fl.

790 Bu "ligatürü-kaldırıldı" kelimelerinin gibi gerçek kelimelerdir usfakat 15.089 kırık kelimelerdir. Kırık kelimelerin 14960'ı orijinal kelimeyle güvenli bir şekilde değiştirilebilir, yani kırık kelimelerin % 99,1'i sabitlenebilir ve bir ligat içeren orijinal kelimelerin % 93,2'si PDF kopyalandıktan sonra kurtarılabilir. Bitişik dizileri içeren kelimelerin % 6,8'i , garantili olmayan kelimelerin her biri için en iyi yerine koymayı seçmek için bir yol seçmezseniz (kelime / belge bağlamı?) Çarpışmalara ( cus) ve alt kelimelere ( us) kaybolur. değiştirme.

Aşağıda yukarıdaki istatistikleri oluşturan Python betiğim var. Her satırda bir kelime olan bir sözlük metin dosyası bekler. Sonunda, düzeltilebilir bozuk kelimeleri orijinal sözcükleriyle eşleyen bir CSV dosyası yazar.

CSV'yi indirmek için bir bağlantı: http://www.filedropper.com/brokenligaturewordfixes Kırık kelimelerin çoğunu değiştirmek için bu eşlemeyi normal ifade değiştirme komut dosyası gibi bir şeyle birleştirin.

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])

Bağlantısı .csvkesildi. Tekrar yükleyebilirseniz bu harika olurdu! Her durumda, kod için teşekkürler.
MagTun

@Enora CSV'yi aynı bağlantıdan tekrar yükledim - umarım yardımcı olur! Ayrıca kodda / sonuçlarda birkaç sorun fark ettim (yeni sözlüğün sözcüklerinde nokta varken noktaların yer tutucu olarak kullanılması ve karşılaştırılmadan önce sözcüklerin küçük harflerle yazılmaması). Tüm değişikliklerin doğru olduğuna inanıyorum, ancak onları bir tuz tanesi ile alın ve daha iyi değiştirmelerin mümkün olduğunu biliyorum. Değiştirmeleri regex ile otomatikleştirmenizi öneririz, ancak daha sonra her değiştirme işleminin kendi gözlerinizle iyi olduğunu onaylayın.
Jan Van Bruggen

8

Buradaki mesele, diğer cevap notlarında olduğu gibi, bitişik harfler ile ilgilidir. Ancak, OpenType ile hiçbir ilgisi yoktur. Temel sorun, PDF'lerin kendisini içerik ve anlambilimle çok az ilgilendiren, bunun yerine bir sayfayı basılacağı gibi sadakatle temsil etmeye yönelik bir baskı öncesi format olmasıdır.

Metin, metin olarak değil , belirli konumlarda bir fonttan glif akışı olarak düzenlenir. Böylece "72 numaralı glifi buraya, 101 numaralı glifi, 108 numaralı glifi buraya yerleştirin ..." gibi bir şey elde edersiniz. O seviyede temelde metin hiçbir kavramı yoktur hiç . Sadece nasıl göründüğüne dair bir açıklama . Bir grup gliften anlam çıkarmada iki sorun vardır:

  1. Mekansal düzen. PDF, her bir glifin nereye yerleştirileceği konusunda belirli bilgiler içerdiğinden, normalde olduğu gibi altında gerçek bir metin yoktur. Bir diğer yan etki de boşluk olmamasıdır. Elbette, metne bakarsanız PDF'de yoktur, ancak yoktur. Hiç bir şey yayamayacağınız zaman neden boş bir glif yaymalısınız? Sonuçta, sonuç aynı. Bu nedenle PDF okuyucuları metni dikkatlice bir araya getirmeli ve glifler arasında daha büyük bir boşlukla karşılaştıklarında boşluk bırakmalıdır.

  2. PDF metin değil glif oluşturur. Çoğu zaman glif kimlikleri, gömülü fontlardaki Unicode kod noktalarına veya en azından ASCII kodlarına karşılık gelir, bu da PDF'yi ilk sırada kimin oluşturduğuna bağlı olarak ASCII veya Latin 1 metnini yeterince iyi geri alabileceğiniz anlamına gelir (bazıları garble herşey sürecinde). Ancak çoğu zaman ASCII metnini iyi çıkarmanıza izin veren PDF'ler bile ASCII olmayan her şeyi değiştirir . Özellikle yerleşim aşamasından sonra yalnızca bitişik harfler ve alternatif glifler içeren Arapça gibi karmaşık komut dosyalarıyla korkunç, bu da Arapça PDF'lerin neredeyse hiç gerçek metin içermediği anlamına gelir

İkinci sorun, karşılaştığınız sorun gibidir. Buradaki yaygın bir suçlu, çıktısını elde etmek için tahmini 238982375 farklı yazı tipini (her biri 256 glifle sınırlıdır) kullanan LaTeX'tir. Normal metin, matematik (birden fazla kullanır) vb. İçin farklı yazı tipleri, özellikle Metafont neredeyse yirmi yıl önce Unicode'dan önce geldiğinden ve böylece hiç bir Unicode eşlemesi olmadığından işleri çok zorlaştırır. Grafikler de bir mektubun üzerine yerleştirilmiş bir diyare ile oluşturulur, örneğin bir PDF'den kopyalarken »ä« yerine »¨a« alırsınız (ve elbette bunu da arayamazsınız).

PDF üreten uygulamalar, gerçek metni meta veri olarak eklemeyi seçebilir. Eğer yapmazlarsa, gömülü fontların nasıl ele alınacağına ve PDF okuyucunun orijinal metni tekrar birleştirip birleştiremeyeceğine merhamet edersiniz. Ancak »fi« boş olarak kopyalanıyor ya da hiç kopyalanmıyor genellikle LaTeX PDF'nin bir işaretidir. Unicode karakterlerini taşların üzerine boyamalı ve XeLaTeX'e geçeceklerini ve böylece 1990'larda karakter kodlamaları ve yazı tipi standartlarına ulaşacaklarını umarak yapımcıya atmalısınız.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.