我遇到了同样的问题。最终,由于对PDF格式的误解,我发现我走错了路。我们将 PDF 文件视为打印机的所见即所得。不是这种情况。在任何类型的打印流程中,PDF 文件通常都会转换为某种中间格式、PostScript、TIFF图像或PCL。
这可能发生在您的本地机器上,这就是您需要驱动程序的原因,也可能发生在打印机本身上。如果它发生在打印机上,您只是将 PDF 文件传输到设置了适当转换系统的另一台计算机上。
这一切都很好而且很花哨,除了PDF 没有定义页面顺序,这对于打印就绪格式来说是非常违反直觉的。这意味着您的文档没有第一页,您将无法以任何方式在本地定义它的形状或形式。
你有两个解决方案:
选择一种打印机架构并使用其独特的设置介质类型的方法,这是一种痛苦且不可移植的方法。
转换为允许设置媒体类型并包含页面排序概念的格式,例如 PostScript。然后添加您的媒体命令并将此文件发送到您的打印机。如果您的打印机有用于读取您选择的中间格式的驱动程序,它应该将命令转换为它的媒体切换版本。这更便携,但仍然不完美。
这类似于将C程序转换为汇编以将其移植到新架构的想法。它主要是有效的,但你必须让每个系统都运行起来。
一个假设的管道将是:
创建您的 PDF 文件 > 通过 PDF 到 PostScript 转换实用程序或库运行它 > 通过自定义词法分析器运行以在每个新页面上添加媒体类型命令 > 将 PostScript 文件发送到打印机
这是很多工作,但这是您唯一能找到解决问题的方法。
样本
%{
char paper[] = 'yourPaper';
%}
%option 8bit outfile="scanner.c"
%option nounput nomain noyywrap
%option warn
%%
showpage { printf("showpage\nsetpagedevice MediaType '%s'", paper); }
%%
int main(int argc, char **argv);
int main (argc,argv)
int argc;
char **argv;
{
yylex();
return 0;
}
上面是一个非常简单的词法分析器,用于查找从 stdin 获得的每个 showpage 命令并输出一个 showpage setpagedevice 命令集。setpagedevice MediaType 命令是设置用于页面的纸张类型的与打印机无关的方式。
使用flex和GCC编译代码:
flex -Cf scanner.l
gcc -O -o lineCount.exe scanner.c
它通过标准输入接受输入并输出到标准输出。
下面列出了一个更完整的词法分析器。它使用 GNU getopts作为命令行选项,并且有两个规则,因此它也会为第一页设置页面设备。它可能无法完美抓取页面,并且它只有一个用于纸张类型的变量,因此功能有限。另一方面,它非常开放,但您希望它确定要使用的页面设备。
识别正在查看的页面类型的新规则,或者每页一行一行的附加输入文件是立即想到的两个。
/*
* This file is part of flex.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE.
*/
/**************************************************
Start of definitions section
***************************************************/
%{
/* A template scanner file to build "scanner.c". */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
/*#include "parser.h" */
//put your variables here
char FileName[256];
FILE *outfile;
char inputName[256];
char paper[] = 'yourPaper';
// flags for command line options
static int specificFile_flag = 0;
static int output_flag = 0;
static int help_flag = 0;
%}
%option 8bit outfile="scanner.c"
%option nounput nomain noyywrap
%option warn
%%
/************************************************
start of rules section
*************************************************/
/* These flex patterns will eat all input */
EndSetup { printf("showpage\nsetpagedevice MediaType '%s'", paper); }
showpage { printf("showpage\nsetpagedevice MediaType '%s'", paper); }
%%
/****************************************************
Start of code section
*****************************************************/
int main(int argc, char **argv);
int main (argc,argv)
int argc;
char **argv;
{
/****************************************************
The main method drives the program. It gets the filename from the
command line, and opens the initial files to write to. Then it calls the lexer.
After the lexer returns, the main method finishes out the report file,
closes all of the open files, and prints out to the command line to let the
user know it is finished.
****************************************************/
int c;
// The GNU getopt library is used to parse the command line for flags
// afterwards, the final option is assumed to be the input file
while (1) {
static struct option long_options[] = {
/* These options set a flag. */
{"help", no_argument, &help_flag, 1},
/* These options don't set a flag. We distinguish them by their indices. */
{"useStdOut", no_argument, 0, 'o'},
{0, 0, 0, 0}
};
/* getopt_long stores the option index here. */
int option_index = 0;
c = getopt_long (argc, argv, "o",
long_options, &option_index);
/* Detect the end of the options. */
if (c == -1)
break;
switch (c) {
case 0:
/* If this option set a flag, do nothing else now. */
if (long_options[option_index].flag != 0)
break;
printf ("option %s", long_options[option_index].name);
if (optarg)
printf (" with arg %s", optarg);
printf ("\n");
break;
case 'o':
output_flag = 1;
break;
case '?':
/* getopt_long already printed an error message. */
break;
default:
abort ();
}
}
if (help_flag == 1) {
printf("proper syntax is: traySwitch.exe [OPTIONS]... INFILE OUTFILE\n");
printf("adds tray switching information to postscript file\n\n");
printf("Option list: \n");
printf("-o sets output to stdout\n");
printf("--help print help to screen\n");
printf("\n");
printf("inputfile example: traySwitch.exe test.ps\n");
printf("If infile is left out, then stdin is used for input.\n");
printf("If outfile is a filename, then that file is used.\n");
printf("If there is no outfile, then infile-EDIT.ps is used.\n");
printf("There cannot be an outfile without an infile.\n");
return 0;
}
//Get the filename off the command line and redirect it to input
//if there is no filename or it is a - then use stdin.
if (optind < argc) {
FILE *file;
file = fopen(argv[optind], "rb");
if (!file) {
fprintf(stderr, "Flex could not open %s\n",argv[optind]);
exit(1);
}
yyin = file;
strcpy(inputName, argv[optind]);
}
else {
printf("no input file set, using stdin. Press ctrl-c to quit");
yyin = stdin;
strcpy(inputName, "\b\b\b\b\bagainst stdin");
}
//Increment current place in argument list
optind++;
/********************************************
If no input name, then output set to stdout.
If no output name then copy input name and add -EDIT.csv.
If input name is '-' then output set to stdout,
otherwise use output name.
*********************************************/
if (optind > argc) {
yyout = stdout;
}
else if (output_flag == 1) {
yyout = stdout;
}
else if (optind < argc){
outfile = fopen(argv[optind], "wb");
if (!outfile) {
fprintf(stderr, "Flex could not open %s\n",FileName);
exit(1);
}
yyout = outfile;
}
else {
strncpy(FileName, argv[optind-1], strlen(argv[optind-1])-4);
FileName[strlen(argv[optind-1])-4] = '\0';
strcat(FileName, "-EDIT.ps");
outfile = fopen(FileName, "wb");
if (!outfile) {
fprintf(stderr, "Flex could not open %s\n",FileName);
exit(1);
}
yyout = outfile;
}
yylex();
if (output_flag == 0) {
fclose(yyout);
}
printf("Flex program finished running file %s\n", inputName);
return 0;
}