Bug 1686

Summary: 1Cv80: 2 копии одного листа, двусторонняя печать включена по умолчанию
Product: WINE@Etersoft Reporter: Sergey Lebedev <lebedev.v.sergey>
Component: Печать ; Диалог печатиAssignee: Виталий Перов <vitperov>
Status: CLOSED FIXED QA Contact:
Severity: critical    
Priority: P2 CC: baraka, lav, vostok
Version: 1.0.9Keywords: TO_WINEHQ
Target Milestone: ---   
Hardware: PC   
OS: ALT Linux   
Whiteboard:
Заявки RT: Связано с:
Дата напоминания:
Bug Depends on:    
Bug Blocks: 443, 1687, 1838, 6009    

Description Sergey Lebedev 2008-04-11 14:21:43 MSD
1с формирует документ, изначально не известно какое число листов при печати будет создано. По умолчанию включена двусторонняя печать. Если у документа страниц > чем 2 и число копий >= 2, то происходит печать заданного числа копий документа с двусторонней печатью. Все хорошо.

Если документ состоит из одной страницы и число копий >= 2, то печать идет с обоих сторон листа. Т.е. вместо двух отдельных листов, я получаю один с обеих сторон у этого документа две одинаковые страницы.

В windows при этом все впорядке. Печатается две отдельные страницы.
Comment 1 Sergey Lebedev 2008-04-11 14:23:09 MSD
wine-20080321-alt0.M40.2
libwine-20080321-alt0.M40.2
wine-etersoft-network-1.0.8-alt0.M40.7
Comment 2 Sergey Lebedev 2008-04-11 15:32:01 MSD
(In reply to comment #1)
> wine-20080321-alt0.M40.2
> libwine-20080321-alt0.M40.2
> wine-etersoft-network-1.0.8-alt0.M40.7
> 

Тоже самое с 
libwine-20080404-alt0.M40.2
wine-20080404-alt0.M40.2
Comment 3 Виталий Перов 2008-04-14 17:43:01 MSD
Да, в данном случае, при печати в файл идёт описание двухсторонней печати:
%%BeginFeature: *Duplex DuplexNoTumble
<</Duplex true/Tumble false>>setpagedevice
%%EndFeature

При этом двусторонней печатью занимается сам принтер.
Как я понял, он каждую вторую страницу должен переворачивать.

Пробовал документ, состоящий из одной страницы, но число копий = 2, и документ из двух страниц, число копий = 1. Они имеют идентичную структуру
Comment 4 Виталий Перов 2008-04-14 17:47:13 MSD
Возникла мысль: если документ состоит из 1 страницы, то просто отключать дуплекс.

Думаю, что при этом ошибка останется: когда, например, документ имеет 3 страницы, а и число копий = 2, тогда первая страница второй копии может оказаться не на новом листе, а на предыдущем.

Надо проверить, если так, то проблему надо решать другим способом
Comment 5 Виталий Перов 2008-04-14 18:27:10 MSD
Существует 2 решения проблемы:
1) Вставлять после каждой копии команду (если такая вообще есть) принтеру о том, что следующую страницу надо печатать с нового листа.
2) При нечётном количестве страниц вставлять после каждой копии пустую страницу
Comment 6 Sergey Lebedev 2008-04-14 19:04:24 MSD
(In reply to comment #5)
> Существует 2 решения проблемы:
> 1) Вставлять после каждой копии команду
> (если такая вообще есть) принтеру о том, что
> следующую страницу надо печатать с нового
> листа.
> 2) При нечётном количестве страниц
> вставлять после каждой копии пустую
> страницу
> 

Что будет если еще ставить галку разобрать по копиям при нечетном числе страниц?
Comment 7 Виталий Перов 2008-04-14 19:11:21 MSD
Странно как-то:
Пробовал печатать в файл в Linux в OpenOffice
получается следующее:

PostScript, генерируемый OpenOffice и PostScript,
генерируемый из 1С отличаются по формату,
но тенденция остаётся:

Пробовал документ, состоящий из одной
страницы, но число копий = 2, и документ из
двух страниц, число копий = 1. Они имеют
идентичную структуру.

Вот и получается, что ошибка и в ОpenOffice тоже
Comment 8 Sergey Lebedev 2008-04-14 19:12:32 MSD
(In reply to comment #5)
> Существует 2 решения проблемы:
> 1) Вставлять после каждой копии команду
> (если такая вообще есть) принтеру о том, что
> следующую страницу надо печатать с нового
> листа.
> 2) При нечётном количестве страниц
> вставлять после каждой копии пустую
> страницу
> 

Что будет если еще ставить галку разобрать по копиям при нечетном числе страниц?
Comment 9 Виталий Перов 2008-04-14 19:18:52 MSD
(In reply to comment #8)
> Что будет если еще ставить галку разобрать
> по копиям при нечетном числе страниц?
>
Имеется ввиду галка "Разбить" рядом с числом копий?
Она везде стояла.
А вообще, при количестве страниц 2 (две копии или 2 страницы), она не должна влиять, но надо проверить.

Comment 10 Виталий Перов 2008-04-14 19:29:14 MSD
При 1 странице и 2-мя копиями, при включенном и при выключенном "разбить", выходные файлы получайтся абсолютно идентичными
Comment 11 Виталий Перов 2008-04-14 20:34:11 MSD
Функции WINAPI позволяют только задавать начало/конец документа и начало/конец страницы. А такой комманды как "печатать следующую страницу с нового листа" не предусмотрено.

Очень интересно как в этом случае поступает Windows, но проверить не получается.
Comment 12 Виталий Перов 2008-04-15 12:52:43 MSD
Можно попробовать написать хак, который из диалога узнаёт, количество копий, есть ли двусторонняя печать. Надо ещё откуда-то брать количество страниц в документе.
И тогда, если имеем нечётное число страниц, включена двусторанняя печать, и количество копий больше 1, тогда сразу после EndPage последней страницы каждого документа можно вставлять пустую страницу.

Вообще, выглядит это совсем не красиво. Должен быть другой вариант, но я его пока не вижу
Comment 13 Виталий Перов 2008-04-15 17:34:47 MSD
В OpenOffice на подобную проблему уже был заведён баг:
http://www.openoffice.org/issues/show_bug.cgi?id=22304

Проблема до сих пор не решена.
Comment 14 Vitaly Lipatov 2008-04-15 17:39:14 MSD
Также
http://www.openoffice.org/issues/show_bug.cgi?id=41583
http://www.openoffice.org/issues/show_bug.cgi?id=46953

К сожалению придётся признать, что без наличия устройства мы не сможем
сделать никаких выводов о том, как это должно работать.
Надо хотя бы поставить у нас аналогичные драйвера (какой принтер используется?)
и проверить в Linux, а по возможности и в Windows.
Comment 15 Sergey Lebedev 2008-04-15 17:50:06 MSD
(In reply to comment #14)
> Также
> http://www.openoffice.org/issues/show_bug.cgi?id=41583
> http://www.openoffice.org/issues/show_bug.cgi?id=46953
> 
> К сожалению придётся признать, что без
> наличия устройства мы не сможем
> сделать никаких выводов о том, как это
> должно работать.
> Надо хотя бы поставить у нас аналогичные
> драйвера (какой принтер используется?)
> и проверить в Linux, а по возможности и в Windows.
> 

HP Laser Jet 1320
Comment 16 Виталий Перов 2008-04-15 19:35:07 MSD
протестировали на OpenOffice с принтером HP Laser Jet 1320.
Печатает всё нормально. В файл вставляется пустая страница.

Получается, что если принтер не дуплексный, а выбрана дуплексная печать, то печатается не правильно.
Если же OpenOffice определяет, что принтер дуплексный, то при нечётном количестве страниц вставляет пустую страницу в конце каждой копии.




Comment 17 Виталий Перов 2008-04-15 19:36:47 MSD
Протестировали на 1С 8.0.18.2 - пустая страница не вставляется.

Возможно ошибка в том, что 1С не может узнать о том, что принтер дуплексный.
А возможно, что этим должна заниматься не 1С, а Windows/Wine
Comment 18 Виталий Перов 2008-04-15 19:45:45 MSD
Как я заметил, в Windows для каждой модели принтера свой диалог. Если он не поддерживает дуплексную печать, то там нет соответствующей опции.

А в Wine 1 диалог для всех принтеров, по мы можем выбрать дуплексную печать, хотя принтер на самом деле её не поддерживает

Comment 19 Виталий Перов 2008-04-15 19:47:53 MSD
Пробовал посмотреть запрашивает ли 1С параметры принтера:
Странно, но не запрашивает. Или запрашивает, но каким-то не известным мне способом
Comment 20 Vitaly Lipatov 2008-04-15 19:57:45 MSD
Описание такой же баги с Microsoft Word 97:
http://support.microsoft.com/kb/196857/EN-US/
Comment 21 Виталий Перов 2008-04-15 20:51:17 MSD
пробовал OpenOffice2.1 под Wine - тест не удался так, как ОО генерирует вторую копию не самостояетельно, а ставит принтеру количетсво копий = 2
Comment 22 Виталий Перов 2008-04-15 22:29:35 MSD
пробовал OpenOffice2.4.0 под Wine :
Печатаю 1 страницу, 2 экземпляра с дуплексом
файл состоит из 3-страниц, только 2-я, которая должна быть пустой, тоже содержит текст.
Comment 23 Виталий Перов 2008-04-16 12:31:30 MSD
А вообще, это мало о чём говорит, ведь ОpenOffice под Windows отличается от Линуксового.

Надо проверить ту же самую версию OpenOffice в Windows.

Если она будет нормально печатать (вставлять пустую страницу между копиями), то скорее всего вставкой пустой страницы должна заниматься Windows/Wine.
Если же нормально печатать не будет, значит это была ошибка в OpenOffice.

В предыдущем тесте ОpenOffice как-то определил, что надо вставлять пустую страницу (хоть и вставил не пустую). Значит можно предположить, что получение возможностей принтера в Wine работает нормально.
Вообще это получение работает вызовом функции DeviceCapabilities().
1C почему-то её не вызывает. Надо проверить вызывает ли её OpenOffice
Comment 24 Виталий Перов 2008-04-17 20:27:23 MSD
Не удалось найти драйвера для HP Laser Jet 1320 под Win98
Попробовал печатать в 1С через Хerox DocuPrint 390HC, он тоже поддерживает дуплексную печать, к тому же генерирует файл в формате PostScript.

В данном случае генерируется 2 страницы вместо 3-х.
Comment 25 Виталий Перов 2008-04-19 14:50:35 MSD
Пробовал 1С81 на WinXP c драйвером для hp 1320, поддерживающим PostScript.

В итоге в документе только 1 страница, но количество копий стоит 2.
Странно как-то : в данном случае 1С не сама дублирует документ, а поручает это драйверу принтера, при этом всё должно печататься нормально
Comment 26 Виталий Перов 2008-04-19 14:55:33 MSD
А вообще должен быть какой-то механизм, с помощью которого 1С определяет параметры принтера. Ведь в 1 случае она сама занимается дублированием документа, а в другом - поручает это драйверу принтера.

Думаю вся проблема в том, что под Wine 1С не может определить поддерживает ли драйвер принтера создание нескольких копий, или же она определяет, что не поддерживает (хотя на самом деле принтер это поддерживает)
Comment 27 Виталий Перов 2008-04-19 15:56:37 MSD
Подробнее проверил OpenOffice через Wine.
Как уже говорилось, он вставляет пустую страницу.
Только он, в отличие от 1С, вызывает функцию DeviceCapabilities, и определяет поддерживает ли принтер дуплексную печать
Comment 28 Виталий Перов 2008-04-19 16:54:10 MSD
1C вызывает PSDRV_ExtDeviceMode() оттуда она может получать иформацию об установленном принтере.
Comment 29 Виталий Перов 2008-04-19 17:54:38 MSD
Проверил 1С на WinXP: поставил несколько копий, дуплексную печать не ставил.

В итоге 1С формирует документ, состоящий из 1 страницы и с указаным количеством копий.

Т.е получается что 1С смотрит возможности принтера (скорее всего через PSDRV_ExtDeviceMode() ) и проверяет может ли он сам печатать несколько копий.
Если да, то 1С сама не занимается дублированием, а перекладывает это на драйвер принтера.

В Wine 1С всегда сама формирует нужное количество копий.

Получается, что WINE возвращает неправильную информацию о возможностях принтера
Comment 30 Виталий Перов 2008-04-19 19:28:56 MSD
PSDRV_ExtDeviceMode() первым делом получает данные о выбранном принтере из системы ( вызывает PSDRV_FindPrinterInfo() ).

При этом флаги DM_COPIES и DM_DUPLEX выставлены, а DM_COLLATE сброшен (т.к Wine пока ещё не поддерживает этот режим).

Появилось предположение, что 1С определяет, что DM_COLLATE сброшен, и решает, что ей надо самостоятельном формировать нужное количество копий.

Предположение не подтвердилось. Если сразу после вызова PSDRV_FindPrinterInfo() принудительно выставить флаг DM_COLLATE, то ничего не изменится.
Comment 31 Виталий Перов 2008-04-19 19:54:49 MSD
ещё существуе функция WINSPOOL_GetPrinterDriver(). Она выдаёт информацию о драйвере принтера. 
1С ещё использует. Возможно как-раз через неё она получает характеристики принтера
Comment 32 Виталий Перов 2008-04-21 17:54:12 MSD
WINSPOOL_GetPrinterDriver() записывает в определённый драйвер структуру, описывающую драйвер принтера. Структуры бывают разного уровня (В данном случае уровень 3).
В этой структуре в основном содержатся пути к разным компонентам драйвера
подробнее: http://msdn2.microsoft.com/en-us/library/ms535710(VS.85).aspx

В частности путь к файлу с данными драйвера:
c:\windows\system32\spool\drivers\win40\0\generic.ppd

Данный каталог существует, однако файлов там нет!

Comment 33 Виталий Перов 2008-04-21 18:17:02 MSD
дабавление туда файла от hp 1320 ничего не изменило
Comment 34 Виталий Перов 2008-04-21 18:25:48 MSD
Маловероятно, что 1С напрямую вызывает GetPrinterDriver(). Эта функцию вызывает диалог печати
Comment 35 Виталий Перов 2008-04-22 19:51:50 MSD
ещё вызывается функция GetDeviceCaps() она отвечает в основном за графические возможности принтера, но лучше посмотреть по-подробнее
Comment 36 Виталий Перов 2008-04-24 18:27:28 MSD
Проверил: GetDeviceCaps() отвечает только за графические возможности принтера
Comment 37 Виталий Перов 2008-05-20 21:14:15 MSD
Не вижу ничего лучшего, как попробовать вариант в <Комментарий  #12>

Есть 2 пути:
1) вставлять пустую страницу в функции PSDRV_EndPage() после конца каждого документа.
Тут есть проблема: 1С сама формирует страницы, поэтому скорее всего не удастся узнать сколько страниц в документе

2) ждать конца документа. В этом случае при вызове функции PSDRV_EndDoc() уже будет известно количество страниц. Затем необходимо пробегаться по всему документу , вставлять в нужном месте пустые страницы и изменять номера последующих страниц.
Здесь тоже есть проблемы:
  а) из функции PSDRV_EndDoc() известна только структура, относящаяся к драйверу принтера, а там всегда dmCopies = 1. Таким образом известно общее количество страниц, но неизвестно количество экземпляров документа.
  б) при выполнении  PSDRV_StartPage и PSDRV_EndPage страницы записываются в spool   коммандой WriteSpool16(). А редактировать их там уже намного сложнее
Comment 38 Sergey Lebedev 2008-05-20 21:22:34 MSD
(In reply to comment #37)
> Не вижу ничего лучшего, как попробовать
> вариант в <Комментарий  #12>

С радостью потестируем.
Comment 39 Анатолий Лютин 2008-05-21 19:58:00 MSD
Виталий лучше знает, но, похоже, к середине-концу июня сделает.
Comment 40 Sergey Lebedev 2008-05-22 12:16:47 MSD
(In reply to comment #39)
> Виталий лучше знает, но, похоже, к
> середине-концу июня сделает.
> 

К середине-концу июня, у нас клиент уже уйдет. Ошибка открыта 11.04, время решения ошибки 2 месяца. Это много. 
Comment 41 Vitaly Lipatov 2008-05-22 12:33:33 MSD
Решили, что ещё пытаемся найти, почему 1С не понимает, что драйвер сам
может тиражировать страницы.
Если не получается, единственный вариант - блокировать выставление количества копий >1  в дуплексном режиме.

Да, проблема актуальна и для 1C 7.7
Comment 42 Виталий Перов 2008-05-24 15:57:27 MSD
Появилось возможное решение:

1С вызывает диалог печати, при этом заполняет структуру PrintStructures->lpPrintDlg. В частности указывает там флаг PD_USEDEVMODECOPIESANDCOLLATE, говоря о том, что приложение поддерживает самостоятельное формирование заданного числа копий.

Проверил: структура PrintStructures->lpPrintDlg относистя только к опциям диалога печати и никак не меняется при смене принтера.

Далее сам диалог печати определяет( по биту PD_USEDEVMODECOPIESANDCOLLATE), что 1С способна сама формировать заданное количество копий, поэтому для надёжности (а вдруг драйвер этого не поддерживает) возлагает это на 1С.

А проблема в том, что двухстороннюю печать 1С правильно может осуществлять только посылая на принтер весь документ, и возлагая дублирование копий на драйвер принтера.

Решением в данном случае является принудительная установка флага при двухсторонней печати PD_USEDEVMODECOPIESANDCOLLATE.
Comment 43 Виталий Перов 2008-05-24 16:17:32 MSD
Вообще в Windows всё по-другому:
Если принтер поддерживает формирование заданного количества копий и приложение это поддерживает, то формированием занимается принтер.
В Wine - если приложение это поддерживает, то оно этим и занимается

Думаю надо вызывать смотреть возможности принтера, и если он поддерживает формирование количества копий, то убирать флаг PD_USEDEVMODECOPIESANDCOLLATE.
Comment 44 Виталий Перов 2008-05-24 18:18:03 MSD
Создал патч. Сейчас всё должно работать
Comment 45 Sergey Lebedev 2008-06-10 13:09:59 MSD
(In reply to comment #44)
> Создал патч. Сейчас всё должно работать
> 

Виталий, огромное спасибо.