⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pclgen.c

📁 openmeetings组件之GS openmeetings组件之GS openmeetings组件之GS
💻 C
📖 第 1 页 / 共 3 页
字号:
/******************************************************************************  File:     $Id: pclgen.c,v 1.21 2001/04/29 10:37:08 Martin Rel $  Contents: PCL-generating routines  Author:   Martin Lottermoser, Greifswaldstrasse 28, 38124 Braunschweig,            Germany. E-mail: Martin.Lottermoser@t-online.de.********************************************************************************									      **	Copyright (C) 1999, 2000, 2001 by Martin Lottermoser		      **	All rights reserved						      **									      ********************************************************************************  In the implementation of these and other functions I have mainly used the  following documents:  - Hewlett-Packard    "Technical Reference Guide for the HP DeskJet 500 Series Printers"    First edition, October 1994    Manual Part Number: C2170-90099    (Quoted as "TRG500")  - Hewlett-Packard    "Hewlett-Packard 300 and 400 Series DeskJet Printers - Software Developer's      Guide"    January 1996    (Quoted as "DJ3/4")  - Hewlett-Packard    "HP DeskJet 600/800 Series Printers - Software Developer's PCL Guide"    Fifth edition, October 1997    (Quoted as "DJ6/8")  - Hewlett-Packard    "DeskJet 1120C Printer - Software Developer's PCL Guide"    First printing, December 1997. Version 1.0.    (Quoted as "DJ1120C")  - Hewlett-Packard    "Printer Job Language Technical Reference Manual"    Edition 10, October 1997. HP Part No. 5021-0380.    (Quoted as "PJLTRM")  - Lexmark    "Printer Technical Reference, Version 1.1"    First edition, February 1999    (Quoted as "Lexmark-PTR". It deals with PCL 5 and PCL 6.)  In addition, some other documents are quoted in a form like "BPD02926". These  were obtained from http://www.hp.com, usually from the directory  cposupport/printers/support_doc. BPD02926, for example, (a short description  of PCL commands for series-800 DeskJets) could be found as the file  bpd02926.html in that directory.******************************************************************************//* Configuration management identification */#ifndef lintstatic const char  cm_id[] = "@(#)$Id: pclgen.c,v 1.21 2001/04/29 10:37:08 Martin Rel $";#endif/*****************************************************************************/#ifndef _XOPEN_SOURCE#define _XOPEN_SOURCE	500#endif/* Standard headers */#include <assert.h>#include <errno.h>#include <stdio.h>#include <stdlib.h>#include <string.h>/* Special headers */#include "pclgen.h"/*****************************************************************************//* Prefix for error messages */#define ERRPREF	"? pclgen: "/* The usual array-size macro */#define array_size(a)	(sizeof(a)/sizeof(a[0]))/* Macro to check whether an octet is an ASCII letter. Note that we can't use   the isalpha() function because we might be operating in an internationalized   environment. */#define is_letter(c)  (0x41 <= (c) && (c) <= 0x5A || 0x61 <= (c) && (c) <= 0x7A)/* Same for digits */#define is_digit(c)	(0x30 <= (c) && (c) <= 0x39)/******************************************************************************  Function: pcl3_levels_to_planes  This function returns ceiling(ld(levels)), the number of bitplanes needed to  store the specified number of intensity levels, or 0 if 'levels' is zero.  'levels' must be <= (ULONG_MAX+1)/2.******************************************************************************/unsigned int pcl3_levels_to_planes(unsigned int levels){  unsigned long    power = 1;  unsigned int    planes = 0;  /* power == 2^planes */  while (power < levels) {    power *= 2;	/* multiplication is faster than division */    planes++;  }  /* levels == 0 or 2^(planes-1) < levels <= 2^planes */  return planes;}/******************************************************************************  Function: send_ERG  This function sends an "End Raster Graphics" command to 'out', choosing its  form according to 'level'.******************************************************************************/static void send_ERG(FILE *out, pcl_Level level){  /* PCL: End Raster Graphics/End Raster */  fputs("\033*r", out);  if (pcl_use_oldERG(level)) fputc('B', out);  else if (level == pcl_level_3plus_ERG_both) fputs("bC", out);  else fputc('C', out);  return;}/******************************************************************************  Function: pcl3_init_file  This function must be called to initialize the printer before the first page.  The 'data' should remain constant within a page. Whenever one changes 'data'  between pages, this function should be called again.  The function follows the return code rules described in pclgen.h. It will  perform a number of validity checks on 'data'. No checks will be performed on  fields like 'print_quality' which can be passed to the printer without having  to be interpreted by this component.  The routine will configure the printer such that the top left corner of the  logical page is the top left corner of the printable area in raster space.  The file 'out' should be a binary file for this and all other output  functions.******************************************************************************/int pcl3_init_file(FILE *out, pcl_FileData *data){  pcl_bool needs_CRD = (data->level == pcl_level_3plus_CRD_only);    /* Do we need Configure Raster Data? */  int j;  const pcl_ColorantState *colorant = NULL;  unsigned int maxhres = 0, maxvres = 0;  /* maximal resolutions in ppi */  /* Check validity of the arguments */  {    pcl_bool invalid;    invalid = (out == NULL || data == NULL);    if (invalid)      fputs(ERRPREF "Null pointer passed to pcl3_init_file().\n", stderr);    else {      /* Palette und colorants */      switch(data->palette) {	case pcl_no_palette:	/*FALLTHROUGH*/	case pcl_black: invalid = data->number_of_colorants != 1; break;	case pcl_CMY:   invalid = data->number_of_colorants != 3; break;	case pcl_RGB:   invalid = data->number_of_colorants != 3; break;	case pcl_CMYK:  invalid = data->number_of_colorants != 4; break;	default: invalid = data->number_of_colorants <= 0;      }      if (invalid)	fputs(ERRPREF	  "Palette specification and number of colorants are inconsistent.\n",	  stderr);      else {	if (data->colorant == NULL) colorant = data->colorant_array;	else colorant = data->colorant;	/* First pass over colorants: find minimal and maximal resolutions,	   check the number of intensity levels */	data->minvres = colorant[0].vres;	for (j = 0; j < data->number_of_colorants; j++) {	  if (colorant[j].hres <= 0 || colorant[j].vres <= 0) {	    invalid = TRUE;	    fprintf(stderr, ERRPREF	      "The resolution for colorant %d is not positive: %u x %u ppi.\n",	      j, colorant[j].hres, colorant[j].vres);	  }	  else {	    if (colorant[j].vres < data->minvres)	      data->minvres = colorant[j].vres;	    if (colorant[j].hres > maxhres) maxhres = colorant[j].hres;	    if (colorant[j].vres > maxvres) maxvres = colorant[j].vres;	  }	  if (colorant[j].levels < 2 || 0xFFFF < colorant[j].levels) {	    invalid = TRUE;	    fprintf(stderr, ERRPREF "The number of intensity levels for "	      "colorant %d is %u instead of at least 2 and at most 65535.\n",	      j, colorant[j].levels);	    /* Actually, DJ6/8 p. 68 requires the levels to be in the range	       2-255, but as there are two octets available in the CRD format	       this seems unnecessarily strict. */	  }	}	/* Check for relations between resolutions and the need for CRD */	if (!invalid)  /* this implies that all resolutions are positive */	  for (j = 0; j < data->number_of_colorants; j++) {	    /* If there is more than one resolution or more than 2 levels we	       need CRD. Note that we compare with 'maxhres' in both lines: */	    if (maxhres != colorant[j].hres ||		maxhres != colorant[j].vres || colorant[j].levels > 2)	      needs_CRD = TRUE;	    /*  DJ6/8 states that the highest horizontal resolution must be a		multiple of all lower horizontal resolutions and the same for		the set of vertical resolutions. The reason is not given but		these properties imply that it is possible to operate uniformly		on a grid at the highest resolution.		In contrast, the way in which raster data are transferred		(strips with a height equal to the reciprocal of the lowest		vertical resolution) logically requires that all vertical		resolutions are multiples of the lowest vertical resolution.		This condition is not stated in DJ6/8 but it is satisfied by		all examples given in that document. This includes example 4 on		page 72 which is meant to illustrate the maximum flexibility of		format 2 and which describes a situation where the		corresponding condition does not hold for the horizontal		resolutions.	    */	    if (colorant[j].vres % data->minvres != 0) {	      invalid = TRUE;	      fprintf(stderr, ERRPREF		"The vertical resolution for colorant %d (%u ppi) is not a "		"multiple of the lowest vertical resolution (%u ppi).\n",		j, colorant[j].vres, data->minvres);	    }	    if (maxhres % colorant[j].hres != 0) {	      invalid = TRUE;	      fprintf(stderr, ERRPREF		"The highest horizontal resolution (%u ppi) is not a multiple "		"of the horizontal resolution for colorant %d (%u ppi).\n",		maxhres, j, colorant[j].hres);	    }	    if (maxvres % colorant[j].vres != 0) {	      invalid = TRUE;	      fprintf(stderr, ERRPREF		"The highest vertical resolution (%u ppi) is not a multiple "		"of the vertical resolution for colorant %d (%u ppi).\n",		maxvres, j, colorant[j].vres);	    }	  }      }      if (needs_CRD && data->palette == pcl_RGB) {	invalid = TRUE;	if (data->level == pcl_level_3plus_CRD_only)	  fputs(ERRPREF	    "You can't use an RGB palette at the requested PCL level.\n",	    stderr);	else	  fputs(ERRPREF "The specified structure of resolutions and intensity "	    "levels is not possible with an RGB palette.\n",	    stderr);      }      if (needs_CRD && !pcl_has_CRD(data->level)) {	invalid = TRUE;	fputs(ERRPREF "The specified structure of resolutions and intensity "	  "levels is not possible at the requested PCL level.\n", stderr);      }      if (data->palette == pcl_any_palette) {	needs_CRD = TRUE;	if (!pcl_has_CRD(data->level)) {	  invalid = TRUE;	  fputs(ERRPREF "The specified palette is not possible at the "	    "requested PCL level.\n", stderr);	}      }      if (needs_CRD && (maxhres > 0xFFFF || maxvres > 0xFFFF)) {	fputs(ERRPREF "Resolutions may be at most 65535 ppi when more than one "	  "resolution or more than two intensity levels are requested.\n",	  stderr);	invalid = TRUE;      }      if (data->order_CMYK && data->palette != pcl_CMYK) {	fputs(ERRPREF	  "Ordering bit planes as CMYK instead of KCMY is only meaningful\n"	  "  for a CMYK palette.\n", stderr);	invalid = TRUE;      }      /* Check PJL job name */      if (data->PJL_job != NULL) {	const unsigned char *s = (const unsigned char *)data->PJL_job;	/* Permissible characters are HT and the octets 32-255 with the	   exception of '"' (PJLTRM, with some corrections). */	while (*s != '\0' && (*s == '\t' || 32 <= *s && *s != '"')) s++;	if (*s != '\0') {	  fprintf(stderr,	    ERRPREF "Illegal character in PJL job name (code 0x%02X).\n", *s);	  invalid = TRUE;	}	/* There is a maximum of 80 "significant characters" (PJLTRM).	   According to PJLTRM, p. D-8, "String too long" is a parser warning	   and leads to a part of the command being ignored. I play it safe.	   There would also be a warning for an empty string but we treat that	   case differently anyway (see below). */	if (strlen(data->PJL_job) > 80) {	  fputs(ERRPREF "PJL job name is too long (more than 80 characters).\n",	    stderr);	  invalid = TRUE;	}      }      /* Check PJL personality name */      if (data->PJL_language != NULL) {	const char *s = data->PJL_language;	/* PJLTRM does not give explicit lexical conventions for personality	   names but from general considerations it should be an "alphanumeric	   variable". The latter must start with a letter and may consist of	   letters and digits. */	if (is_letter(*s)) do s++; while (is_letter(*s) || is_digit(*s));	if (*data->PJL_language == '\0') {	  fputs(ERRPREF "Empty PJL language name.\n", stderr);	  invalid = TRUE;	}	else if (*s != '\0') {	  fprintf(stderr,	    ERRPREF "Illegal character in PJL language name (code 0x%02X).\n",	    *s);	  invalid = TRUE;	}      }    }    if (invalid) return +1;  }  /*  Practically every output file from an HP driver I have seen starts with      600 and one even with 9600 NUL characters. This seems unnecessary      and is undocumented, but just in case that there are situations where it      might make a difference, this module provides the capability. */  for (j = 0; j < data->NULs_to_send; j++) fputc('\0', out);  /*  Issue PJL commands if requested. Most newer HP drivers for PCL-3 printers      follow the NULs with a PJL statement to enter the PCL language      interpreter. The language name varies (so far I've seen PCL3GUI and      PCLSLEEK). Some drivers also generate JOB/EOJ statements.      Interestingly enough, I have seen output from two HP drivers which, at      the beginning of the job, generated first Printer Reset and then UEL.      This is wrong (PJLTRM).  */  if (data->PJL_job != NULL || data->PJL_language != NULL) {    fputs("\033%-12345X", out);	/* Universal Exit Language (UEL) */    /* Start of job */    if (data->PJL_job != NULL) {      fputs("@PJL JOB", out);      if (*data->PJL_job != '\0') fprintf(out, " NAME=\"%s\"", data->PJL_job);      fputc('\n', out);    }    /* Switch personality */    if (data->PJL_language != NULL)

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -