Фильтрация символов, отсутствующих в шрифте пользователя в Java - PullRequest
2 голосов
/ 09 февраля 2012

Я хочу создать довольно простую таблицу с использованием Java (в качестве упражнения), чтобы проверить наличие допустимой печатаемой кодовой точки Unicode в шрифте конечного пользователя. Поскольку некоторые шрифты не могут печатать допустимые кодовые точки, я должен знать, какие печатаемые кодовые точки пользовательский шрифт тем не менее отсутствует и поэтому не может печатать.

Например, если шрифт поддерживает только латинские символы, я не могу печатать греческие символы, используя его, не говоря уже о японских символах. Юникод говорит, что все они пригодны для печати, но шрифт пользователя может быть недостаточно хорошим.

После небольшого исследования я смог напечатать большинство символов в Eclipse (с помощью настройки кодировки). Однако у меня все еще есть несколько неизвестных / непечатаемых символов в моем выводе, потому что когда я смотрю на вывод, я вижу все эти пустые прямоугольники для некоторых из моих печатаемых символов.

Я пытался их отфильтровать, но не могу найти способ сделать это. К вашему сведению, я просто устанавливаю значение символа на 50, 100 или 1000, а затем увеличиваю его с помощью цикла for, чтобы проверить, какие символы я могу или не могу (или не должен?) Печатать.

Кто-нибудь может дать мне несколько советов о том, с чего начать?

Ответы [ 2 ]

3 голосов
/ 09 февраля 2012

Ваша задача на самом деле немного сложнее, чем кодирование, потому что шрифт, из которого вы пытаетесь напечатать, имеет большое значение в выводе.Т.е. не все шрифты поддерживают одинаковый набор символов.На самом деле поддержка диапазонов символов сильно отличается от шрифта к шрифту .

Тем не менее, ваша проблема теперь становится такой: Как я могу определить, поддерживает ли определенный шрифт данный символ?И этот вопрос был задан и получен ответ ... Здесь вы найдете документацию по Java для функции canDisplay , которая является членом класса Font .

2 голосов
/ 09 февраля 2012

Непонятно, что вы на самом деле и именно здесь имеете в виду.Если вы планируете играть по номерам, то Приложение C Технического стандарта Unicode # 18 на Регулярные выражения Unicode дает конкретное предположение, что «печатная» кодовая точка должна быть определена как любой кодточка, имеющая свойство print, где это свойство определено как

  • \p{print} означает [[\p{graph}\p{blank}]&&[^\p{gc=Control}]]
  • \p{graph} означает [^\p{Whitespace}\p{gc=Control}\p{gc=Surrogate}\p{gc=Unassigned}]
  • \p{blank} означает [\p{Whitespace}&&[^\N{LF}\N{VT}\N{FF}\N{CR}\N{NEL}\p{gc=Line_Separator}\{gc=Paragraph_Separator}]

Или , поскольку класс Java 1.7 Pattern документирует эти , при условии, что вы скомпилируете шаблон с new-to-Java7 Pattern.UNICODE_CHARACTER_CLASS флаг включен:

  • \p{Graph} Видимый символ: [^\p{IsWhite_Space}\p{gc=Cc}\p{gc=Cs}\p{gc=Cn}]
  • \p{Print} Печатный символ: [\p{Graph}\p{Blank}&&[^\p{Cntrl}]]
  • \p{Blank} Пробел или табуляция: [\p{IsWhite_Space}&&[^\p{gc=Zl}\p{gc=Zp}\x0a\x0b\x0c\x0d * \x85]]
  • \p{Cntrl} Управляющий символ: \p{gc=Cc}
  • \p{XDigit} Шестнадцатеричная цифра: [\p{gc=Nd}\p{IsHex_Digit}]
  • \p{Space} Пробельный символ: \p{IsWhite_Space}

На «печатных» символах

Если вы просто используете что-то разумное, например Java (?U)\p{print} pсвойство attern (или эквивалент класса Character), тогда у вас еще есть некоторые «интересные» решения.

Рассмотрим каждый из следующих кодовых пунктов:

U+000007 gc=Cc columns=0 print=0 graph=0  ALERT
U+000008 gc=Cc columns=0 print=0 graph=0  BACKSPACE
U+000009 gc=Cc columns=0 print=0 graph=0  CHARACTER TABULATION
U+00000C gc=Cc columns=0 print=0 graph=0  FORM FEED (FF)
U+00000D gc=Cc columns=0 print=0 graph=0  CARRIAGE RETURN (CR)
U+000020 gc=Zs columns=1 print=1 graph=0  SPACE
U+000021 gc=Po columns=1 print=1 graph=1  EXCLAMATION MARK
U+000041 gc=Lu columns=1 print=1 graph=1  LATIN CAPITAL LETTER A
U+000061 gc=Ll columns=1 print=1 graph=1  LATIN SMALL LETTER A
U+000080 gc=Cc columns=0 print=0 graph=0  PADDING CHARACTER
U+000085 gc=Cc columns=0 print=0 graph=0  NEXT LINE (NEL)
U+00008D gc=Cc columns=0 print=0 graph=0  REVERSE LINE FEED
U+0000AB gc=Pi columns=1 print=1 graph=1  LEFT-POINTING DOUBLE ANGLE QUOTATION MARK
U+0000AD gc=Cf columns=0 print=1 graph=1  SOFT HYPHEN
U+0002B0 gc=Lm columns=1 print=1 graph=1  MODIFIER LETTER SMALL H
U+0002C6 gc=Lm columns=1 print=1 graph=1  MODIFIER LETTER CIRCUMFLEX ACCENT
U+000302 gc=Mn columns=0 print=1 graph=1  COMBINING CIRCUMFLEX ACCENT
U+00036A gc=Mn columns=0 print=1 graph=1  COMBINING LATIN SMALL LETTER H
U+001100 gc=Lo columns=2 print=1 graph=1  HANGUL CHOSEONG KIYEOK
U+002028 gc=Zl columns=0 print=0 graph=0  LINE SEPARATOR
U+002029 gc=Zp columns=0 print=0 graph=0  PARAGRAPH SEPARATOR
U+00202B gc=Cf columns=0 print=1 graph=1  RIGHT-TO-LEFT EMBEDDING
U+00202F gc=Zs columns=1 print=1 graph=0  NARROW NO-BREAK SPACE
U+002060 gc=Cf columns=0 print=1 graph=1  WORD JOINER
U+002061 gc=Cf columns=0 print=1 graph=1  FUNCTION APPLICATION
U+002062 gc=Cf columns=0 print=1 graph=1  INVISIBLE TIMES
U+002064 gc=Cf columns=0 print=1 graph=1  INVISIBLE PLUS
U+002EC1 gc=So columns=2 print=1 graph=1  CJK RADICAL TIGER
U+002F0B gc=So columns=2 print=1 graph=1  KANGXI RADICAL EIGHT
U+003000 gc=Zs columns=2 print=1 graph=0  IDEOGRAPHIC SPACE
U+003008 gc=Ps columns=2 print=1 graph=1  LEFT ANGLE BRACKET
U+00300A gc=Ps columns=2 print=1 graph=1  LEFT DOUBLE ANGLE BRACKET
U+00300C gc=Ps columns=2 print=1 graph=1  LEFT CORNER BRACKET
U+00302B gc=Mn columns=0 print=1 graph=1  IDEOGRAPHIC RISING TONE MARK
U+003030 gc=Pd columns=2 print=1 graph=1  WAVY DASH
U+003037 gc=So columns=2 print=1 graph=1  IDEOGRAPHIC TELEGRAPH LINE FEED SEPARATOR SYMBOL
U+003041 gc=Lo columns=2 print=1 graph=1  HIRAGANA LETTER SMALL A
U+00E000 gc=Co columns=1 print=1 graph=1 <unnamed codepoint in blk=Private_Use_Area>
U+00F8FF gc=Co columns=1 print=1 graph=1 <unnamed codepoint in blk=Private_Use_Area>
U+00FB1E gc=Mn columns=0 print=1 graph=1  HEBREW POINT JUDEO-SPANISH VARIKA
U+00FE00 gc=Mn columns=0 print=1 graph=1  VARIATION SELECTOR-1
U+00FE23 gc=Mn columns=0 print=1 graph=1  COMBINING DOUBLE TILDE RIGHT HALF
U+00FE58 gc=Pd columns=2 print=1 graph=1  SMALL EM DASH
U+00FE77 gc=Lo columns=1 print=1 graph=1  ARABIC FATHA MEDIAL FORM
U+00FEFF gc=Cf columns=0 print=1 graph=1  ZERO WIDTH NO-BREAK SPACE
U+00FF06 gc=Po columns=2 print=1 graph=1  FULLWIDTH AMPERSAND
U+00FFFA gc=Cf columns=0 print=1 graph=1  INTERLINEAR ANNOTATION SEPARATOR
U+00FFFD gc=So columns=1 print=1 graph=1  REPLACEMENT CHARACTER
U+01B000 gc=Lo columns=2 print=1 graph=1  KATAKANA LETTER ARCHAIC E
U+01D165 gc=Mc columns=1 print=1 graph=1  MUSICAL SYMBOL COMBINING STEM
U+01D167 gc=Mn columns=0 print=1 graph=1  MUSICAL SYMBOL COMBINING TREMOLO-1
U+100002 gc=Co columns=1 print=1 graph=1 <unnamed codepoint in blk=Supplementary_Private_Use_Area-B>

Некоторые из них весьма условны относительно того, что и, возможно, даже печатают ли они.Например, как U + F8FF ‹› выглядит для вас?

Тогда вам нужно решить, как обрабатывать табуляцию и возврат.

Кроме того, вам придется учитывать различные \p{Grapheme_Extend} кодовые точки, используемые для построения кластера расширенных графем Unicode ;то есть видимый пользователю символ .Не все из них являются непроходными отметками.На самом деле, это не знаки, а буквы!Некоторые не являются печатными символами вообще, и все же они изменяют печатный символ \p{Grapheme_Base}, к которому они неизбежно прикреплены;Рассмотрим в качестве одного из примеров селекторы вариаций.

Предупреждение

Что приводит нас к критически важному моменту, который слишком часто забывают будущие программисты на Java, и даже когда он не полностью забыт,обычно недооценивается.

Всегда, всегда, всегда помните, что символы Java не являются символами Unicode! Существует два разумных определения символа Unicode, и Java дает вамни.Вот два разумных определения:

  • Если символ является символом в программистско-видимом смысле, то символ - это кодовая точка Unicode.Это то, что . соответствует в механизме регулярных выражений, например, независимо от того, используете ли вы Sun или ICU.
  • Если символ является символом в видимом для пользователя смысле , тосимвол - это расширенный кластер графем Unicode.Это то, что \X соответствует в модуле регулярных выражений (ICU не Sun).

Так называемый «символ» Java - это низкоуровневый, прерывисто-абстрактный 2-байтовый элементUTF-16 переменной ширины представляет фактическую кодовую точку Unicode.Это не абстрактная кодовая точка и не абстрактная графема.Это не абстракт ничего. Java char является нарушением оболочки абстракции.

Да, некоторые классы Java предоставляют вам интерфейс codePointAt, и вы должны использовать его везде, где это возможно.Но во многих отношениях, которые здесь объясняются слишком долго, Java в корне нарушает свою символьную абстракцию - потому что у нее ее нет.

Это делает работу с символами и строками Юникода в лучшем случае подверженной ошибкам в Java, а часто почти невозможной.

Удачи.

...