Ошибка в библиотеке /usr/openwin/server/lib/libfont.so при растризации шрифтов TrueType в Solaris 8 x86

Имеется ошибка в программе libfont.so. Она проявляется при растризации так называемых композитных глифов (Composite Glyph) шрифтов TrueType.

Эта ошибка известна как BugID 4546277. И вот как Sun её замотал:

Bug ID    Synopsis                                                                 Date
4546277   S8 - Solaris 8 X86 (intel) displays Cyrillic TrueType fonts incorrectly  29 Jan 2002

Product                   sunos
Category                  library
Subcategory               l10n-europe
Bug-RFE-EOU               bug
State                     incomplete
Development Status        NYI
Keywords                  TrueType, ansi-1251, font, koi8-r, no-s9+, s9-reviewed
Severity                  2
Severity Impact           1
Severity Functionality    0

Priority                  2
Responsible Manager: XXXXXXXX
Responsible Engineer: XXXXXXXX

Description

Please see screenshot in attachment. Some letters in Arial, Courier and Times
TrueType koi8-r and and ansi-1251 displayed incorrectly (wrong kerning).

For example:

xfd -fn "-monotype-arial-regular-r-*-*-*-*-*-*-*-*-koi8-r"
characters 0x00dc and 0x00fc have incorrect metrics - displayed outside of
rectangle.

The same fonts look fine and are diplayed correctly on Solaris Sparc.

Justification             These are the only koi-8 and ansi-1251 fonts supplied in Solaris
Work Around               (none)
Suggested Fix             (none)

State Triggers

Accepted:                 yes
Evaluated:                no

Evaluation                (none)
Commit to fix in releases (none)
Fixed in releases         (none)
Integrated in releases    (none)
Verified in releases      (none)
Closed because            (none)
Incomplete because        need more info
Duplicate of              (none)
Introduced in release     (none)
Root Cause                (none)
Program Management        (none)
Fix Affects Documentation no
Exempt from dev rel       no
Fix affects L10N          no
Interest List             XXXXXX.XXXXXXX@sun.com, XXXXXX@omega.ru
Patch ID                  (none)

Comments
=============================================================================

X.XXX@sun.com 2002-01-14

Sol8 UR has finished. This is not occurring in Solaris 9.

This occurs in Solaris 8 FCS.
If you need a patch for Solaris 8, you will need to escalate the bug.
The patch will include updated files in
 /usr/openwin/lib/locale/KOI8-R/X11/fonts/TrueType

If not, then this bug will be closed after 1 working week

=============================================================================
See also:

Hooks
Hook 1:
        Hook 2:
        Hook 3:
        Hook 4:
        Hook 5:
        Hook 6:

History

Submitter:                        XXXXXXXX Date: Dec  4 2001  1:31AM
        Dispatch operator:                 bugtraq Date: Dec  4 2001  1:31AM
        Acceptor:                          XXXXXXX Date: Dec 11 2001  6:16AM
        Evaluator:                                 Date:
        Commit operator:                           Date:
        Fix operator:                              Date:
        Integrating operator:                      Date:
        Verify operator:                           Date:
        Closeout operator:                         Date:

Called in by

Customer:
        Company: Sun Microsystems Russia
        Employee: XXXXXXX XXXXXXXX
        User Role: D, Development
        User Type: I, Internal (SMI) Customer
        Release: s28u6_08
        Hardware Version: x86
        O/S version (unbundled products): 5.8
        SO Number:
        Sun Contact: XXXXXXXX
        Contact Name:
        Contact Mailaddr:

Переписка с X.XXX@sun.com ничего не дала.

Однако перейдём к делу.

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

Например, глиф буквы 'Ё' может быть композитным и состоять из двух простых: 'Е' и "двоеточия", причём глиф 'Е' может использоваться самостоятельно, а "двоеточие" входить в состав других композитных глифов - 'ё' и некоторых других символов, входящих в набор iso8859-1.

rockwell

Другой пример - глифы букв 'R' и 'Я'. Один из них, обычно 'R' является простым, а другой ('Я') композитным. Он получается путём масштабирования простого глифа с коэффициентом -1 по X и +1 по Y и сдвига по оси X.

Использование композитных глифов уменьшает размер файла шрифта TrueType, потому, что вместо длинной программы отрисовки глифа в файл шрифта помещается несколько двухбайтовых чисел (в формате BIG_ENDIAN) описывающих матрицу преобразования.

При установленных по-умолчанию путях к шрифтам, ошибка растризации композитных глифов видна только при работе под кириллическими локализациями ru_RU.KOI8-R и ru_RU.ANSI1251. В локализации же ru_RU.ISO8859-5 пути к шрифтам установлены так, что система перед TrueType, выбирает шрифты Adobe Type1 с теми-же именами, которые растризуются правильно.

Солярис 8 имеет 12 TrueType шрифтов:

$ uname -a
SunOS lev 5.8 Generic_108528-11 sun4u sparc SUNW,Ultra-1
$ pwd
/usr/openwin/lib/locale/euro_fonts/X11/fonts/TrueType
$ ls -l
total 4336
-rw-r--r--   1 root     bin       147664 Окт 13  1999 ArialBold.ttf
-rw-r--r--   1 root     bin       167488 Окт 13  1999 ArialBoldItalic.ttf
-rw-r--r--   1 root     bin       147084 Окт 13  1999 ArialItalic.ttf
-rw-r--r--   1 root     bin       146436 Окт 13  1999 ArialRegular.ttf
-rw-r--r--   1 root     bin       176860 Окт 13  1999 CourierBold.ttf
-rw-r--r--   1 root     bin       182284 Окт 13  1999 CourierBoldItalic.ttf
-rw-r--r--   1 root     bin       190660 Окт 13  1999 CourierItalic.ttf
-rw-r--r--   1 root     bin       175336 Окт 13  1999 CourierRegular.ttf
-rw-r--r--   1 root     bin       186032 Окт 13  1999 TimesBold.ttf
-rw-r--r--   1 root     bin       174588 Окт 13  1999 TimesBoldItalic.ttf
-rw-r--r--   1 root     bin       184644 Окт 13  1999 TimesItalic.ttf
-rw-r--r--   1 root     bin       192332 Окт 13  1999 TimesRegular.ttf

Это шрифты в формате unicode, и они содержат глифы букв всех европейских языков. Выбор того или иного набора осуществляется с помощью задания encoding-вектора для требуемой локализации.

Некоторые, неправильно отображаемые, русские буквы "прямых" (не "italic") шрифтов выполнены в виде композитных глифов:

Основной глиф:                            Композитный глиф:

CYRILLIC CAPITAL LETTER UKRAINIAN IE  ->  CYRILLIC CAPITAL LETTER E
afii10053, unicode 0x0404                 afii10047, unicode 0x042d

CYRILLIC SMALL LETTER UKRAINIAN IE    ->  CYRILLIC SMALL LETTER E
afii10101, unicode 0x0454                 afii10095, unicode 0x044d

Latin-1 letter R (unicode 0x052)      ->  CYRILLIC CAPITAL LETTER YA
                                          afii10049, unicode 0x042f

В результате проявления ошибки получаем:

Click here to enlarge Click here to enlarge

Не следует думать, что только русским (украинцам, белорусcам etc.) не повезло. Испаноговорящие товарищи имеют аналогичные проблемы с символами '!' и '?'. Эти символы используются в начале восклицательного и вопросительного предложений в "перевёрнутом" виде (exclamdown, questiondown) и оформлены в некоторых TrueType шрифтах как композитные глифы. Смотри, например, /usr/openwin/lib/X11/fonts/TrueType/GillSans-BoldItalic.ttf

Ошибка обусловлена неправильным считыванием данных матрицы масштабирования из описания символа в таблице glyf шрифта TrueType. Эта матрица считывается из файла шрифта при обработке флагового бита WE_HAVE_AN_X_AND_Y_SCALE или WE_HAVE_A_TWO_BY_TWO. При считывании данных необходимо не только переставить порядок байт, но и обеспечить расширение знака при присваивании четырёхбайтовым числам значений двухбайтовых чисел.

Нижеследующий фрагмент текста, часто используемый и, возможно, оформленный в программе libfont.so.1 как макро, читает два байта данных по адресу 4(%eax), переставляет их, но не расширяет знак для отрицательных чисел:

3c2f0:  66 8b 50 04           movw   4(%eax),%dx ; Загрузка 2-х байт. Байт содержащий
						; старшие разряды числа - попадёт в %dl,
						; байт содержащий младшие разряды числа
						; попадёт в %dh
3c2f4:  0f bf ca              movswl %dx,%ecx
3c2f7:  c1 f9 08              sarl   $0x8,%ecx	; В %ecx младший байт. Знаковый бит расширен
						; на весь регистр %ecx. Расширение знака
						; лишено смысла, поскольку нужно расширять
						; знаковый бит старшего байта. Мало того,
						; следующие команда затирают три старших
						; байта регистров %ecx и %edx нулями
3c2fa:  0f b6 c9              movzbl %cl,%ecх	; Младший байт
3c2fd:  0f b6 d2              movzbl %dl,%edx	; Старший байт, здесь и надо расширить
						; знак, т.е. применить команду movsbl
3c300:  c1 e2 08              shll   $0x8,%edx 
3c303:  0b ca                 orl    %edx,%ecx  ; Байты числа переставлены, однако отрицательные
						; числа превращаются в положительные.
3c305:  c1 e1 02              shll   $0x2,%ecx  ; Масштабирование
3c308:  89 8d 34 ff ff ff     movl   %ecx,-0xcc(%ebp)

Ошибка не проявляется на Солярис 8 для SPARC.

Детрансляция и анализ кода показали, что исходный код программы libfont.so.1 различен для SPARC и x86. Причём у меня сложилось впечатление, что в для SPARC растризация TrueType шрифтов сделана более корректно.

Программу можно поправить. Поскольку исходный код недоступен, то исправления придётся вносить в двоичный код библиотеки libfont.so.1. Дополнительной сложностью является то, что в зависимости от версии патча на X программа libfont.so.1 имеет различное распределение адресов.

Далее описана процедура поиска адресов команд, которые должны быть исправлены.

Выполните команды:

$ su
Password: 
# cd /usr/openwin/server/lib
# cp -p libfont.so.1 libfont.so.1.orig
# exit
$ cd $HOME
$ mkdir libfont
$ cd libfont
$ dis /usr/openwin/server/lib/libfont.so.1.orig > libfont.so.1.orig.dis

В файле libfont.so.1.orig.dis найдите функцию sfnt_ReadSFNT() и сравните её текст с нижеприведённым. Запишите адреса команд в Вашем листинге, которые необходимо скорректировать. В нижеприведённом листинге команды, которые необходимо скорректировать отмечены символами '-->':

sfnt_ReadSFNT()
   3bfb8:  55                    pushl  %ebp
   3bfb9:  8b ec                 movl   %esp,%ebp
   3bfbb:  81 ec d0 00 00 00     subl   $0xd0,%esp
   3bfc1:  53                    pushl  %ebx
   3bfc2:  56                    pushl  %esi
   3bfc3:  57                    pushl  %edi
   3bfc4:  e8 00 00 00 00        call   .+5
   3bfc9:  5b                    popl   %ebx
   3bfca:  81 c3 37 80 01 00     addl   $0x18037,%ebx
   3bfd0:  c7 45 c4 00 00 00 00  movl   $0x0,-0x3c(%ebp)
   3bfd7:  c7 45 fc 00 00 00 00  movl   $0x0,-4(%ebp)
   3bfde:  c7 45 f8 00 00 00 00  movl   $0x0,-8(%ebp)
   3bfe5:  66 8b 45 10           movw   0x10(%ebp),%ax
   3bfe9:  50                    pushl  %eax
   3bfea:  ff 75 08              pushl  8(%ebp)
   3bfed:  e8 1a e3 fc ff        call   sfnt_ReadSFNTMetrics
   3bff2:  83 c4 08              addl   $0x8,%esp
   3bff5:  8d 45 c4              leal   -0x3c(%ebp),%eax
   3bff8:  50                    pushl  %eax
   3bff9:  8d 45 c0              leal   -0x40(%ebp),%eax
   3bffc:  50                    pushl  %eax
   3bffd:  66 8b 45 10           movw   0x10(%ebp),%ax
   3c001:  50                    pushl  %eax
   3c002:  ff 75 08              pushl  8(%ebp)
   3c005:  e8 a6 fe ff ff        call   sfnt_GetGlyphLocation
   3c00a:  8b 45 c4              movl   -0x3c(%ebp),%eax
   3c00d:  23 c0                 andl   %eax,%eax
   3c00f:  0f 8e af 00 00 00     jle    .+0xb5	[0x3c0c4]
   3c015:  6a 01                 pushl  $0x1
   3c017:  6a 06                 pushl  $0x6
   3c019:  50                    pushl  %eax
   3c01a:  ff 75 c0              pushl  -0x40(%ebp)
   3c01d:  ff 75 08              pushl  8(%ebp)
   3c020:  e8 f7 f9 ff ff        call   sfnt_GetDataPtr
   3c025:  89 45 f8              movl   %eax,-8(%ebp)	; адрес таблицы glif
	
   3c028:  66 8b 08              movw   (%eax),%cx
   3c02b:  0f bf c1              movswl %cx,%eax
   3c02e:  c1 f8 08              sarl   $0x8,%eax
   3c031:  0f b6 c0              movzbl %al,%eax
   3c034:  0f b6 c9              movzbl %cl,%ecx
   3c037:  c1 e1 08              shll   $0x8,%ecx
   3c03a:  66 0b c8              orw    %ax,%cx
   3c03d:  66 89 4d a4           movw   %cx,-0x5c(%ebp)	; число контуров numberOfContours
	
   3c041:  8b 45 f8              movl   -8(%ebp),%eax
   3c044:  66 8b 70 02           movw   2(%eax),%si	; xMin
   3c048:  0f bf c6              movswl %si,%eax
   3c04b:  c1 f8 08              sarl   $0x8,%eax
   3c04e:  0f b6 d0              movzbl %al,%edx
   3c051:  8b c6                 movl   %esi,%eax
   3c053:  0f b6 c0              movzbl %al,%eax
   3c056:  c1 e0 08              shll   $0x8,%eax
   3c059:  66 0b c2              orw    %dx,%ax
   3c05c:  66 89 45 b8           movw   %ax,-0x48(%ebp)
	
   3c060:  8b 45 f8              movl   -8(%ebp),%eax
   3c063:  66 8b 70 04           movw   4(%eax),%si	; yMin
   3c067:  0f bf c6              movswl %si,%eax
   3c06a:  c1 f8 08              sarl   $0x8,%eax
   3c06d:  0f b6 d0              movzbl %al,%edx
   3c070:  8b c6                 movl   %esi,%eax
   3c072:  0f b6 c0              movzbl %al,%eax
   3c075:  c1 e0 08              shll   $0x8,%eax
   3c078:  66 0b c2              orw    %dx,%ax
   3c07b:  66 89 45 ba           movw   %ax,-0x46(%ebp)
	
   3c07f:  8b 45 f8              movl   -8(%ebp),%eax
   3c082:  66 8b 50 06           movw   6(%eax),%dx	; xMax
   3c086:  0f bf c2              movswl %dx,%eax
   3c089:  c1 f8 08              sarl   $0x8,%eax
   3c08c:  0f b6 c0              movzbl %al,%eax
   3c08f:  0f b6 d2              movzbl %dl,%edx
   3c092:  c1 e2 08              shll   $0x8,%edx
   3c095:  66 0b d0              orw    %ax,%dx
   3c098:  66 89 55 bc           movw   %dx,-0x44(%ebp)
	
   3c09c:  8b 45 f8              movl   -8(%ebp),%eax
   3c09f:  66 8b 50 08           movw   8(%eax),%dx	; yMax
   3c0a3:  0f bf c2              movswl %dx,%eax
   3c0a6:  c1 f8 08              sarl   $0x8,%eax
   3c0a9:  0f b6 c0              movzbl %al,%eax
   3c0ac:  0f b6 d2              movzbl %dl,%edx
   3c0af:  c1 e2 08              shll   $0x8,%edx
   3c0b2:  66 0b d0              orw    %ax,%dx
   3c0b5:  66 89 55 be           movw   %dx,-0x42(%ebp)
	
   3c0b9:  8b 75 f8              movl   -8(%ebp),%esi
   3c0bc:  83 c6 0a              addl   $0xa,%esi	; esi -> data for glyph
   3c0bf:  eb 0d                 jmp    .+0xf	[0x3c0ce]
   3c0c1:  90                    nop    
   3c0c2:  90                    nop    
   3c0c3:  90                    nop    
   3c0c4:  66 c7 45 a4 01 00     movw   $0x1,-0x5c(%ebp)
   3c0ca:  66 b9 01 00           movw   $0x1,%cx
   3c0ce:  66 23 c9              andw   %cx,%cx		; число контуров?
   3c0d1:  0f 8c a5 00 00 00     jl     .+0xab	[0x3c17c] ; jmp, если compound
   3c0d7:  8b 45 c4              movl   -0x3c(%ebp),%eax
   3c0da:  89 45 f0              movl   %eax,-0x10(%ebp)
   3c0dd:  8b 45 08              movl   8(%ebp),%eax
   3c0e0:  66 83 b8 e6 01 00 00 00 cmpw   $0x0,0x1e6(%eax)
   3c0e8:  74 0b                 je     .+0xd	[0x3c0f5]
   3c0ea:  66 8b 80 e8 01 00 00  movw   0x1e8(%eax),%ax
   3c0f1:  a8 20                 testb  $0x20,%al
   3c0f3:  75 07                 jne    .+9	[0x3c0fc]
   3c0f5:  ba 01 00 00 00        movl   $0x1,%edx
   3c0fa:  eb 02                 jmp    .+4	[0x3c0fe]
   3c0fc:  2b d2                 subl   %edx,%edx
   3c0fe:  8b 45 08              movl   8(%ebp),%eax
   3c101:  66 89 90 22 02 00 00  movw   %dx,0x222(%eax)
   3c108:  83 7d f0 00           cmpl   $0x0,-0x10(%ebp)
   3c10c:  7e 2f                 jle    .+0x31	[0x3c13d]
   3c10e:  89 75 a8              movl   %esi,-0x58(%ebp)
   3c111:  0f bf d1              movswl %cx,%edx
	
   3c114:  66 8b 0c 56           movw   (%esi,%edx,2),%cx
   3c118:  0f bf c1              movswl %cx,%eax
   3c11b:  c1 f8 08              sarl   $0x8,%eax
   3c11e:  0f b6 c0              movzbl %al,%eax
   3c121:  0f b6 c9              movzbl %cl,%ecx
   3c124:  c1 e1 08              shll   $0x8,%ecx
   3c127:  66 0b c8              orw    %ax,%cx
	
   3c12a:  66 89 4d ac           movw   %cx,-0x54(%ebp)
   3c12e:  8d 54 56 02           leal   2(%esi,%edx,2),%edx
   3c132:  89 55 b0              movl   %edx,-0x50(%ebp)
   3c135:  0f bf c1              movswl %cx,%eax
   3c138:  03 c2                 addl   %edx,%eax
   3c13a:  89 45 b4              movl   %eax,-0x4c(%ebp)
   3c13d:  ff 75 0c              pushl  0xc(%ebp)
   3c140:  ff 75 f0              pushl  -0x10(%ebp)
   3c143:  8d 45 9c              leal   -0x64(%ebp),%eax
   3c146:  50                    pushl  %eax
   3c147:  8d 45 a0              leal   -0x60(%ebp),%eax
   3c14a:  50                    pushl  %eax
   3c14b:  8d 45 a4              leal   -0x5c(%ebp),%eax
   3c14e:  50                    pushl  %eax
   3c14f:  ff 75 08              pushl  8(%ebp)
   3c152:  e8 41 f2 ff ff        call   sfnt_UnfoldCurve
   3c157:  8b f0                 movl   %eax,%esi
   3c159:  23 f6                 andl   %esi,%esi
   3c15b:  0f 85 9c 03 00 00     jne    .+0x3a2	[0x3c4fd]
   3c161:  6a 00                 pushl  $0x0
   3c163:  ff 75 9c              pushl  -0x64(%ebp)
   3c166:  ff 75 a0              pushl  -0x60(%ebp)
   3c169:  8d 45 b8              leal   -0x48(%ebp),%eax
   3c16c:  50                    pushl  %eax
   3c16d:  ff 75 18              pushl  0x18(%ebp)
   3c170:  8a 45 14              movb   0x14(%ebp),%al
   3c173:  89 45 f4              movl   %eax,-0xc(%ebp)
   3c176:  e9 67 03 00 00        jmp    .+0x36c	[0x3c4e2]
   3c17b:  90                    nop    
	
   3c17c:  66 83 f9 ff           cmpw   $-0x1,%cx
   3c180:  66 b8 00 00           movw   $0x0,%ax
   3c184:  0f 94 c0              sete   %eax
   3c187:  8b 4d 08              movl   8(%ebp),%ecx
   3c18a:  66 89 81 e6 01 00 00  movw   %ax,0x1e6(%ecx)
   3c191:  66 23 c0              andw   %ax,%ax
   3c194:  0f 84 5e 03 00 00     je     .+0x364	[0x3c4f8]
   3c19a:  c7 45 ec 00 00 00 00  movl   $0x0,-0x14(%ebp)
   3c1a1:  8b 45 0c              movl   0xc(%ebp),%eax
   3c1a4:  89 45 e8              movl   %eax,-0x18(%ebp)
   3c1a7:  8b 45 18              movl   0x18(%ebp),%eax
   3c1aa:  89 45 e4              movl   %eax,-0x1c(%ebp)
   3c1ad:  8a 45 14              movb   0x14(%ebp),%al
   3c1b0:  89 45 f4              movl   %eax,-0xc(%ebp)
	
					; -0x20(%ebp) ptr на component glyph part description
   3c1b3:  89 75 e0              movl   %esi,-0x20(%ebp)
	
   3c1b6:  8b 4d e0              movl   -0x20(%ebp),%ecx
   3c1b9:  66 8b 09              movw   (%ecx),%cx	; component flag
   3c1bc:  0f bf c1              movswl %cx,%eax
   3c1bf:  c1 f8 08              sarl   $0x8,%eax
   3c1c2:  0f b6 f0              movzbl %al,%esi
   3c1c5:  0f b6 f9              movzbl %cl,%edi
   3c1c8:  c1 e7 08              shll   $0x8,%edi
   3c1cb:  8b c6                 movl   %esi,%eax
   3c1cd:  66 0b c7              orw    %di,%ax
   3c1d0:  89 45 dc              movl   %eax,-0x24(%ebp) ; 0x24(%ebp) component flag 
   3c1d3:  8b 45 e0              movl   -0x20(%ebp),%eax
   3c1d6:  66 8b 48 02           movw   2(%eax),%cx	; gliphIndex
   3c1da:  0f bf c1              movswl %cx,%eax
   3c1dd:  c1 f8 08              sarl   $0x8,%eax
   3c1e0:  0f b6 c0              movzbl %al,%eax
   3c1e3:  0f b6 c9              movzbl %cl,%ecx
   3c1e6:  c1 e1 08              shll   $0x8,%ecx
   3c1e9:  0b c8                 orl    %eax,%ecx
   3c1eb:  89 4d d8              movl   %ecx,-0x28(%ebp) ; gliphIndex	
   3c1ee:  8b 45 e0              movl   -0x20(%ebp),%eax
   3c1f1:  05 04 00 00 00        addl   $0x4,%eax	; X-offset
   3c1f6:  8b d6                 movl   %esi,%edx
   3c1f8:  80 e2 01              andb   $0x1,%dl
   3c1fb:  8b cf                 movl   %edi,%ecx
   3c1fd:  80 e1 01              andb   $0x1,%cl
   3c200:  0a d1                 orb    %cl,%dl
   3c202:  74 38                 je     .+0x3a	[0x3c23c]
   3c204:  8b 4d e0              movl   -0x20(%ebp),%ecx
   3c207:  66 8b 51 04           movw   4(%ecx),%dx
   3c20b:  0f bf ca              movswl %dx,%ecx
   3c20e:  c1 f9 08              sarl   $0x8,%ecx
   3c211:  0f b6 c9              movzbl %cl,%ecx
   3c214:  0f b6 d2              movzbl %dl,%edx
   3c217:  c1 e2 08              shll   $0x8,%edx
   3c21a:  66 0b d1              orw    %cx,%dx
   3c21d:  89 55 d4              movl   %edx,-0x2c(%ebp)
   3c220:  05 02 00 00 00        addl   $0x2,%eax
   3c225:  66 8b 10              movw   (%eax),%dx
   3c228:  0f bf ca              movswl %dx,%ecx
   3c22b:  c1 f9 08              sarl   $0x8,%ecx
   3c22e:  0f b6 c9              movzbl %cl,%ecx
   3c231:  0f b6 d2              movzbl %dl,%edx
   3c234:  c1 e2 08              shll   $0x8,%edx
   3c237:  66 0b d1              orw    %cx,%dx
   3c23a:  eb 2f                 jmp    .+0x31	[0x3c26b]
   3c23c:  8b d6                 movl   %esi,%edx
   3c23e:  80 e2 02              andb   $0x2,%dl
   3c241:  8b cf                 movl   %edi,%ecx
   3c243:  80 e1 02              andb   $0x2,%cl
   3c246:  0a d1                 orb    %cl,%dl
   3c248:  8b 4d e0              movl   -0x20(%ebp),%ecx
   3c24b:  74 13                 je     .+0x15	[0x3c260]
   3c24d:  0f be 49 04           movsbl 4(%ecx),%ecx
   3c251:  89 4d d4              movl   %ecx,-0x2c(%ebp)
   3c254:  8b 4d e0              movl   -0x20(%ebp),%ecx
   3c257:  0f be 49 05           movsbl 5(%ecx),%ecx
   3c25b:  89 4d d0              movl   %ecx,-0x30(%ebp)
   3c25e:  eb 0e                 jmp    .+0x10	[0x3c26e]
   3c260:  0f b6 51 04           movzbl 4(%ecx),%edx
   3c264:  89 55 d4              movl   %edx,-0x2c(%ebp)
   3c267:  0f b6 51 05           movzbl 5(%ecx),%edx
   3c26b:  89 55 d0              movl   %edx,-0x30(%ebp)
   3c26e:  8d 48 02              leal   2(%eax),%ecx
					; -0x20(%ebp) ptr на transformation option 
   3c271:  89 4d e0              movl   %ecx,-0x20(%ebp)
   3c274:  f6 45 dc c8           testb  $0xc8,-0x24(%ebp)
   3c278:  0f 84 7b 01 00 00     je     .+0x181	[0x3c3f9] ; jmp, если нет флагов масштабирования
   3c27e:  8b 4d 08              movl   8(%ebp),%ecx
   3c281:  81 c1 0c 01 00 00     addl   $0x10c,%ecx
   3c287:  89 4d cc              movl   %ecx,-0x34(%ebp)
   3c28a:  8b 4d 08              movl   8(%ebp),%ecx
   3c28d:  81 c1 30 01 00 00     addl   $0x130,%ecx
   3c293:  89 4d c8              movl   %ecx,-0x38(%ebp)
   3c296:  8b 55 08              movl   8(%ebp),%edx
   3c299:  8d bd 78 ff ff ff     leal   -0x88(%ebp),%edi
   3c29f:  8d b2 0c 01 00 00     leal   0x10c(%edx),%esi
   3c2a5:  fc                    cld    
   3c2a6:  b9 09 00 00 00        movl   $0x9,%ecx
   3c2ab:  f3 a5                 repz movsl (%esi),(%edi)
   3c2ad:  8d bd 54 ff ff ff     leal   -0xac(%ebp),%edi
   3c2b3:  8d b2 30 01 00 00     leal   0x130(%edx),%esi
   3c2b9:  fc                    cld    
   3c2ba:  b9 09 00 00 00        movl   $0x9,%ecx
   3c2bf:  f3 a5                 repz movsl (%esi),(%edi)
   3c2c1:  c7 45 ec 01 00 00 00  movl   $0x1,-0x14(%ebp)
   3c2c8:  f6 45 dc 80           testb  $0x80,-0x24(%ebp) ; WE HAVE_A_TWO_BY_TWO
   3c2cc:  0f 84 9e 00 00 00     je     .+0xa4	[0x3c370]
	
   3c2d2:  66 8b 50 02           movw   2(%eax),%dx	; xscale
   3c2d6:  0f bf ca              movswl %dx,%ecx
   3c2d9:  c1 f9 08              sarl   $0x8,%ecx
   3c2dc:  0f b6 c9              movzbl %cl,%ecx
-->3c2df:  0f b6 d2              movzbl %dl,%edx
   3c2e2:  c1 e2 08              shll   $0x8,%edx
   3c2e5:  0b ca                 orl    %edx,%ecx
   3c2e7:  c1 e1 02              shll   $0x2,%ecx
   3c2ea:  89 8d 30 ff ff ff     movl   %ecx,-0xd0(%ebp)
	
   3c2f0:  66 8b 50 04           movw   4(%eax),%dx	; scale01
   3c2f4:  0f bf ca              movswl %dx,%ecx
   3c2f7:  c1 f9 08              sarl   $0x8,%ecx
   3c2fa:  0f b6 c9              movzbl %cl,%ecx
-->3c2fd:  0f b6 d2              movzbl %dl,%edx
   3c300:  c1 e2 08              shll   $0x8,%edx
   3c303:  0b ca                 orl    %edx,%ecx
   3c305:  c1 e1 02              shll   $0x2,%ecx
   3c308:  89 8d 34 ff ff ff     movl   %ecx,-0xcc(%ebp)
	
   3c30e:  66 8b 50 06           movw   6(%eax),%dx	; scale10
   3c312:  0f bf ca              movswl %dx,%ecx
   3c315:  c1 f9 08              sarl   $0x8,%ecx
   3c318:  0f b6 c9              movzbl %cl,%ecx
-->3c31b:  0f b6 d2              movzbl %dl,%edx
   3c31e:  c1 e2 08              shll   $0x8,%edx
   3c321:  0b ca                 orl    %edx,%ecx
   3c323:  c1 e1 02              shll   $0x2,%ecx
   3c326:  89 8d 3c ff ff ff     movl   %ecx,-0xc4(%ebp)
	
   3c32c:  66 8b 50 08           movw   8(%eax),%dx	; yscale
   3c330:  0f bf c2              movswl %dx,%eax
   3c333:  c1 f8 08              sarl   $0x8,%eax
   3c336:  0f b6 c8              movzbl %al,%ecx
-->3c339:  0f b6 c2              movzbl %dl,%eax
   3c33c:  c1 e0 08              shll   $0x8,%eax
   3c33f:  0b c1                 orl    %ecx,%eax
   3c341:  83 45 e0 08           addl   $0x8,-0x20(%ebp) ; продвижение указателя по файлу
   3c345:  c1 e0 02              shll   $0x2,%eax
   3c348:  89 85 40 ff ff ff     movl   %eax,-0xc0(%ebp)
	
   3c34e:  ff 75 cc              pushl  -0x34(%ebp)
   3c351:  8d b5 30 ff ff ff     leal   -0xd0(%ebp),%esi
   3c357:  56                    pushl  %esi
   3c358:  e8 6f e0 fc ff        call   fsg_MxConcat2x2
   3c35d:  83 c4 08              addl   $0x8,%esp
   3c360:  ff 75 c8              pushl  -0x38(%ebp)
   3c363:  56                    pushl  %esi
   3c364:  e8 63 e0 fc ff        call   fsg_MxConcat2x2
   3c369:  83 c4 08              addl   $0x8,%esp
   3c36c:  eb 76                 jmp    .+0x78	[0x3c3e4]
   3c36e:  90                    nop    
   3c36f:  90                    nop    
	
   3c370:  f6 45 dc 40           testb  $0x40,-0x24(%ebp) ; WE_HAVE_AN_X_AND_Y_SCALE
   3c374:  74 36                 je     .+0x38	[0x3c3ac]
	
   3c376:  66 8b 50 02           movw   2(%eax),%dx	; xscale
   3c37a:  0f bf ca              movswl %dx,%ecx
   3c37d:  c1 f9 08              sarl   $0x8,%ecx
   3c380:  0f b6 f1              movzbl %cl,%esi
-->3c383:  0f b6 ca              movzbl %dl,%ecx
   3c386:  c1 e1 08              shll   $0x8,%ecx
   3c389:  0b f1                 orl    %ecx,%esi
   3c38b:  c1 e6 02              shll   $0x2,%esi
	
   3c38e:  66 8b 48 04           movw   4(%eax),%cx	; yscale
   3c392:  0f bf c1              movswl %cx,%eax
   3c395:  c1 f8 08              sarl   $0x8,%eax
   3c398:  0f b6 c0              movzbl %al,%eax
-->3c39b:  0f b6 f9              movzbl %cl,%edi
   3c39e:  c1 e7 08              shll   $0x8,%edi
   3c3a1:  0b f8                 orl    %eax,%edi
   3c3a3:  83 45 e0 04           addl   $0x4,-0x20(%ebp) ; продвижение указателя по файлу
   3c3a7:  c1 e7 02              shll   $0x2,%edi
	
   3c3aa:  eb 1e                 jmp    .+0x20	[0x3c3ca]
	
   3c3ac:  66 8b 48 02           movw   2(%eax),%cx
   3c3b0:  0f bf c1              movswl %cx,%eax
   3c3b3:  c1 f8 08              sarl   $0x8,%eax
   3c3b6:  0f b6 c0              movzbl %al,%eax 
-->3c3b9:  0f b6 f9              movzbl %cl,%edi
   3c3bc:  c1 e7 08              shll   $0x8,%edi
   3c3bf:  0b f8                 orl    %eax,%edi
   3c3c1:  83 45 e0 02           addl   $0x2,-0x20(%ebp) ; продвижение указателя по файлу
   3c3c5:  c1 e7 02              shll   $0x2,%edi
	
   3c3c8:  8b f7                 movl   %edi,%esi
   3c3ca:  ff 75 cc              pushl  -0x34(%ebp)
   3c3cd:  57                    pushl  %edi
   3c3ce:  56                    pushl  %esi
   3c3cf:  e8 08 e0 fc ff        call   fsg_MxScaleAB
   3c3d4:  83 c4 0c              addl   $0xc,%esp
   3c3d7:  ff 75 c8              pushl  -0x38(%ebp)
   3c3da:  57                    pushl  %edi
   3c3db:  56                    pushl  %esi
   3c3dc:  e8 fb df fc ff        call   fsg_MxScaleAB
   3c3e1:  83 c4 0c              addl   $0xc,%esp
   3c3e4:  ff 75 08              pushl  8(%ebp)
   3c3e7:  e8 e0 de fc ff        call   fsg_InitInterpreterTrans
   3c3ec:  83 c4 04              addl   $0x4,%esp
   3c3ef:  8b 45 08              movl   8(%ebp),%eax
   3c3f2:  c6 80 54 01 00 00 00  movb   $0x0,0x154(%eax)
   3c3f9:  8b 4d dc              movl   -0x24(%ebp),%ecx
   3c3fc:  8b 45 08              movl   8(%ebp),%eax
   3c3ff:  66 89 88 e8 01 00 00  movw   %cx,0x1e8(%eax)
   3c406:  8b 4d d4              movl   -0x2c(%ebp),%ecx
   3c409:  66 89 88 ea 01 00 00  movw   %cx,0x1ea(%eax)
   3c410:  8b 4d d0              movl   -0x30(%ebp),%ecx
   3c413:  66 89 88 ec 01 00 00  movw   %cx,0x1ec(%eax)
	
   3c41a:  ff 75 e4              pushl  -0x1c(%ebp)
   3c41d:  8b 45 f4              movl   -0xc(%ebp),%eax
   3c420:  50                    pushl  %eax
   3c421:  ff 75 d8              pushl  -0x28(%ebp)
   3c424:  ff 75 e8              pushl  -0x18(%ebp)
   3c427:  ff 75 08              pushl  8(%ebp)
   3c42a:  e8 4d df fc ff        call   sfnt_ReadSFNT
   3c42f:  83 c4 14              addl   $0x14,%esp
   3c432:  8b f0                 movl   %eax,%esi
   3c434:  80 7d ec 00           cmpb   $0x0,-0x14(%ebp)
   3c438:  74 42                 je     .+0x44	[0x3c47c]
   3c43a:  8b 45 08              movl   8(%ebp),%eax
   3c43d:  56                    pushl  %esi
   3c43e:  8d b8 0c 01 00 00     leal   0x10c(%eax),%edi
   3c444:  8d b5 78 ff ff ff     leal   -0x88(%ebp),%esi
   3c44a:  fc                    cld    
   3c44b:  b9 09 00 00 00        movl   $0x9,%ecx
   3c450:  f3 a5                 repz movsl (%esi),(%edi)
   3c452:  5e                    popl   %esi
   3c453:  50                    pushl  %eax
   3c454:  e8 73 de fc ff        call   fsg_InitInterpreterTrans
   3c459:  83 c4 04              addl   $0x4,%esp
   3c45c:  8b 45 08              movl   8(%ebp),%eax
   3c45f:  56                    pushl  %esi
   3c460:  8d b8 30 01 00 00     leal   0x130(%eax),%edi
   3c466:  8d b5 54 ff ff ff     leal   -0xac(%ebp),%esi
   3c46c:  fc                    cld    
   3c46d:  b9 09 00 00 00        movl   $0x9,%ecx
   3c472:  f3 a5                 repz movsl (%esi),(%edi)
   3c474:  c7 45 ec 00 00 00 00  movl   $0x0,-0x14(%ebp)
   3c47b:  5e                    popl   %esi
   3c47c:  f6 45 dc 20           testb  $0x20,-0x24(%ebp) ; jmp, если есть ещё компоненты
   3c480:  74 08                 je     .+0xa	[0x3c48a]
   3c482:  23 f6                 andl   %esi,%esi
   3c484:  0f 84 2c fd ff ff     je     .-0x2ce	[0x3c1b6]
   3c48a:  8b 7d dc              movl   -0x24(%ebp),%edi
   3c48d:  8b 75 e0              movl   -0x20(%ebp),%esi
   3c490:  66 8b 45 10           movw   0x10(%ebp),%ax
   3c494:  50                    pushl  %eax
   3c495:  ff 75 08              pushl  8(%ebp)
   3c498:  e8 6f de fc ff        call   sfnt_ReadSFNTMetrics
   3c49d:  83 c4 08              addl   $0x8,%esp
   3c4a0:  66 f7 c7 00 01        testw  $0x100,%di
   3c4a5:  74 25                 je     .+0x27	[0x3c4cc]
   3c4a7:  66 8b 0e              movw   (%esi),%cx
   3c4aa:  0f bf c1              movswl %cx,%eax
   3c4ad:  c1 f8 08              sarl   $0x8,%eax
   3c4b0:  0f b6 c0              movzbl %al,%eax
   3c4b3:  0f b6 c9              movzbl %cl,%ecx
   3c4b6:  c1 e1 08              shll   $0x8,%ecx
   3c4b9:  66 0b c8              orw    %ax,%cx
   3c4bc:  0f b7 c1              movzwl %cx,%eax
   3c4bf:  89 45 fc              movl   %eax,-4(%ebp)
   3c4c2:  89 45 a0              movl   %eax,-0x60(%ebp)
   3c4c5:  8d 46 02              leal   2(%esi),%eax
   3c4c8:  eb 08                 jmp    .+0xa	[0x3c4d2]
   3c4ca:  90                    nop    
   3c4cb:  90                    nop    
   3c4cc:  8b 45 fc              movl   -4(%ebp),%eax
   3c4cf:  89 45 a0              movl   %eax,-0x60(%ebp)
   3c4d2:  89 45 9c              movl   %eax,-0x64(%ebp)
   3c4d5:  6a 01                 pushl  $0x1
   3c4d7:  50                    pushl  %eax
   3c4d8:  ff 75 fc              pushl  -4(%ebp)
   3c4db:  8d 45 b8              leal   -0x48(%ebp),%eax
   3c4de:  50                    pushl  %eax
   3c4df:  ff 75 e4              pushl  -0x1c(%ebp)
   3c4e2:  0f b6 45 f4           movzbl -0xc(%ebp),%eax
   3c4e6:  50                    pushl  %eax
   3c4e7:  ff 75 08              pushl  8(%ebp)
   3c4ea:  e8 fd de fc ff        call   fsg_InnerGridFit
   3c4ef:  83 c4 1c              addl   $0x1c,%esp
   3c4f2:  8b f0                 movl   %eax,%esi
   3c4f4:  eb 07                 jmp    .+9	[0x3c4fd]
   3c4f6:  90                    nop    
   3c4f7:  90                    nop    
   3c4f8:  be 07 14 00 00        movl   $0x1407,%esi
   3c4fd:  83 7d f8 00           cmpl   $0x0,-8(%ebp)
   3c501:  74 0c                 je     .+0xe	[0x3c50f]
   3c503:  ff 75 f8              pushl  -8(%ebp)
   3c506:  8b 45 08              movl   8(%ebp),%eax
   3c509:  ff 50 08              call   *8(%eax)
   3c50c:  83 c4 04              addl   $0x4,%esp
   3c50f:  8b c6                 movl   %esi,%eax
   3c511:  5f                    popl   %edi
   3c512:  5e                    popl   %esi
   3c513:  5b                    popl   %ebx
   3c514:  c9                    leave  
   3c515:  c3                    ret    
   3c516:  00                    .byte	0
   3c517:  00                    .byte	0

Т.е. для данного экземпляра libfont.so.1 необходимо заменить команды movzbl на movsbl по адресам:

0x3c2df
0x3c2fd
0x3c31b
0x3c339
0x3c383
0x3c39b
0x3c3b9

Для этого используйте программу:

/*
 *    patch.c
 *
 *   (C) Vitaly Filatov, https://members.tripod.com/Vitaly_Filatov Mar 2002
 *
 */

#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>

#define SOURCE_FILE	"/usr/openwin/lib/libfont.so.1.orig"
#define DEST_FILE	"/tmp/libfont.so.1"

int main()
{
    int in, out, ret, k;
    long length;
    char *buf;

    in = open(SOURCE_FILE, O_RDONLY);
    if (in == -1) {
	printf("Can't open source file\n");
	exit(1);
    }
    out = open(DEST_FILE, O_CREAT | O_RDWR, 0775);
    if (out == -1) {
	printf("Can't open dest file\n");
	exit(1);
    }
    length = lseek(in, 0L, SEEK_END);
    lseek(in, 0L, SEEK_SET);
    buf = (char *) malloc(length);
    if (buf == NULL) {
	printf("Can't malloc\n");
	exit(1);
    }
    ret = read(in, buf, length);
    if (ret != length) {
	printf("ret = %d : Can't read source file\n", ret);
	exit(1);
    }

/* Заменяйте адреса здесь: */

    k = 0x3c2df;		/* xscale */
    buf[k++] = 0x0f;
    buf[k++] = 0xbe;
    k = 0x3c2fd;		/* scale01 */
    buf[k++] = 0x0f;
    buf[k++] = 0xbe;
    k = 0x3c31b;		/* scale10 */
    buf[k++] = 0x0f;
    buf[k++] = 0xbe;
    k = 0x3c339;		/* yscale */
    buf[k++] = 0x0f;
    buf[k++] = 0xbe;

    k = 0x3c383;		/* xscale */
    buf[k++] = 0x0f;
    buf[k++] = 0xbe;
    k = 0x3c39b;		/* yscale */
    buf[k++] = 0x0f;
    buf[k++] = 0xbe;

    k = 0x3c3b9;		/* xscale = yscale */
    buf[k++] = 0x0f;
    buf[k++] = 0xbe;

    write(out, buf, length);
    close(in);
    close(out);
    return 0;
}

Сохраните эту программу под именем patch.c и выполните команды:

$ gcc -o patch patch.c
$ ./patch

Программа создаст новую версию библиотеки libfont.so.1 в каталоге /tmp. Для проверки правильности изменения команд, Вы можете дизассемблировать модифицированную программу /tmp/libfont.so.1.

Затем, выйдите из графической оболочки (CDE, OpenWindows, и т.д.) и войдите в систему как пользователь root в режиме командной строки.

Выполните команды:

# cd /tmp
# chown root:bin libfont.so.1
# cp -p libfont.so.1 /usr/openwin/server/lib

Всё готово. Загрузите графическую оболочку и проверьте правильность растризации шрифтов (звёздочками отмечены те шрифты, которые ранее растризовались неправильно):

 $ xset +fp /usr/openwin/lib/locale/iso_8859_5/X11/fonts/TrueType
 $ xfd -fn "-monotype-arial-bold-r-normal--30-300-0-0-p-0-iso8859-5"
 $ xfd -fn "-monotype-arial-bold-i-normal--30-300-0-0-p-0-iso8859-5"
 $ xfd -fn "-monotype-arial-regular-i-normal--30-300-0-0-p-0-iso8859-5"
*$ xfd -fn "-monotype-arial-regular-r-normal--30-300-0-0-p-0-iso8859-5"
*$ xfd -fn "-monotype-courier-bold-r-normal--30-300-0-0-m-0-iso8859-5"
 $ xfd -fn "-monotype-courier-bold-i-normal--30-300-0-0-m-0-iso8859-5"
 $ xfd -fn "-monotype-courier-regular-i-normal--30-300-0-0-m-0-iso8859-5"
*$ xfd -fn "-monotype-courier-regular-r-normal--30-300-0-0-m-0-iso8859-5"
*$ xfd -fn "-monotype-times-bold-r-normal--30-300-0-0-p-0-iso8859-5"
 $ xfd -fn "-monotype-times-bold-i-normal--30-300-0-0-p-0-iso8859-5"
 $ xfd -fn "-monotype-times-regular-i-normal--30-300-0-0-p-0-iso8859-5"
*$ xfd -fn "-monotype-times-regular-r-normal--30-300-0-0-p-0-iso8859-5"
 $ xset -fp /usr/openwin/lib/locale/iso_8859_5/X11/fonts/TrueType

Имеется ещё одна ошибка (очевидно не последняя), которую пока исправить не удалось. Шрифт garait.ttf -monotype-Garamond-medium-i-normal--0-0-0-0-p-0-iso8859-15 взят из набора шрифтов MS Windows 98:

Click here to enlarge

Глиф неверно воспроизводимой буквы 'CE' является простым. Остальные шрифты из Win31, Win98 растризуются правильно.

Все TrueType шрифты штатно включённые в Солярис растризуются правильно. При загрузке StarOffice Вы можете поставить пути к TrueType шрифтам первыми.

Я попробовал также многие TrueType шрифты с компакт-диска

"Виртуальная библиотека компьютерных шрифтов 2001"
(C) 2001 DELTA.MM Corp.
(C) 2001 "Навигатор" (ООО "Программа 2000") www.cdboom.com

На диске можно найти более-менее правильно сформированные TrueType шрифты. Однако неправильно "encoded" шрифтов довольно много. Также, довольно редко, видны некоторые погрешности растризации, однако трудно понять вызваны ли они ошибками libfont.so.1 или это ошибки кодирования самих шрифтов. Требуется дополнительное разбирательство.

Файл fonts.scale создавался программой ttmkfdir из XFree86, скомпилированной в Солярисе. Программа ttmkfdir для Солярис 8 x86 находится здесь. Чтобы подключить шрифты к X11 выполните команды:

$ cd в каталог со шрифтами
$ ttmkfdir > fonts.scale
$ mkfontdir
$ xset +fp `pwd`

This page last updated on Mar 25, 2002. Copyright © 2002, Vitaly Filatov, Moscow, Russia
Webmaster