DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T p

⟦e44cf276a⟧ TextFile

    Length: 17908 (0x45f4)
    Types: TextFile
    Names: »pos.c«

Derivation

└─⟦52210d11f⟧ Bits:30007239 EUUGD2: TeX 3 1992-12
    └─⟦af5ba6c8e⟧ »unix3.0/DVIWARE.tar.Z« 
        └─⟦ca79c7339⟧ 
            └─⟦this⟧ »DVIware/laser-setters/dvi-to-ps/TeXPS/dvitps/src/pos.c« 

TextFile

/* Copyright 1988 Stephan v. Bechtolsheim */

/* This file is part of the TeXPS Software Package.

The TeXPS Software Package is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY.  No author or distributor
accepts responsibility to anyone for the consequences of using it
or for whether it serves any particular purpose or works at all,
unless he says so in writing.  Refer to the TeXPS Software Package
General Public License for full details.

Everyone is granted permission to copy, modify and redistribute
the TeXPS Software Package, but only under the conditions described in the
TeXPS Software Package General Public License.   A copy of this license is
supposed to have been given to you along with TeXPS Software Package so you
can know your rights and responsibilities.  It should be in a
file named CopyrightLong.  Among other things, the copyright notice
and this notice must be preserved on all copies.  */


#include <stdio.h>
#include "defs.h"
#include "units.h"
#include "dvitps.h"
#include "extfil.h"
#include "fontd.h"
#include "dvi-com.h"
#include "pdr.h"
#include "emit.h"

/* DEBUG definitions:
   POSITIONING_TESTING: turn on the whole machinery of comparing the positions
   in the printer with the positions as computed by this driver. If enabled
   must turn on the same definition in pass1.c. */

/* MAX_DRIFT_EXTRA_CHECK: if that symbol defined, after a maxdrift control
   an extra check is performed, making sure that the maxdrift
   business works. */

/* This is the maximum number of pixels the "tfm width" and the
 * "pixel width" as imported through the .gf, .pk or .pxl file
 * can differ, before a warning is generated by this driver. No
 * warning is generated when precisely this value is reached. */
#define MAX_PIXELS_TFM_RW 2

/* Define how long the string collected by SetString() can be as maximum.
   This value * 4 could be the maximum of the actual PostScript string
   produced by that, because certain characters are encoded as octal
   numbers and become \000 type of characters. */
#define LCC_MAX 20

/* Externals. */
extern void PssSendCommand();
extern void PssSendInteger();
extern int PssColumn;
extern FE_P Fonts[MAX_FONTS];
extern FE_P CurFontPointer;
extern int CurFontNumber;
extern EX_FILES ExDvi;
extern EX_FILES Ex_PsOutput;
extern double ConvertPosPoints();
extern int Resolution;
extern int   HConv, VConv;
extern DVIU  h;
extern DVIU  hh;
extern DVIU  v;
extern DVIU  vv;
extern int Verbose;
extern void PssFlushStringAndPos();
extern int PssStringIndex;
extern char PssStringBuffer[1];
extern int PssNeedSpaceMatrix[4][4];
extern int PssLastThingSent;

/* Forward declarations. */
void PrintPositions();
PXLU PixRound();

/* Is such warning, as outlined above, generated in the first places? */
int MaxPixelsWarning = FALSE;

/* If set to TRUE all movements are absolute and no maxdrift check takes place
 * any more. Can also done with '-Q2'! */
int AllMovementsAbsolute = FALSE;

#ifdef DEBUG
int CommandOffsetPositioning; /* Offset, dvi file command, for positining business.
				 Local to this module. */
#endif

/* What are the maxdrift values in DVIUs? */
DVIU MaxDriftHorizontal; /* Positive */
DVIU MaxDriftHorizontalNeg; /* Negative */
DVIU MaxDriftVertical; /* Same */
DVIU MaxDriftVerticalNeg;

/* Incremented if there was a real correction. */
int MaxDriftHCount = 0;
int MaxDriftVCount = 0;

/* Forward declarations of those procedures. */
int MaxDriftH();
int MaxDriftV();

/* Movements horizontally and vertically to be done by the printer
 * (hh and vv already reflect those movements) but which have not
 * been sent to the printer yet */
PXLU AccDeltaH;
PXLU AccDeltaV;

/* Threshold below which movements are relative rather than absolute. */
DVIU ThresholdMovementHP;
DVIU ThresholdMovementHN;
DVIU ThresholdMovementVP;
DVIU ThresholdMovementVN;

#ifdef POSITIONING_TESTING
EX_FILES ExPosFile;
#endif

/*
 * ChangeFontAndSetup
 * ******************
 * Change font: set up all the stuff, especially all the threshold
 * parameters. The new font number has been previously loaded
 * into CurFontNumber by the code in Pass1(). The execution of
 * this routine is triggered by a font change code in the dvi file.
 * This routine is only called by Pass1().
 */
void
ChangeFontAndSetup ()
{
  int basis;

  if (CurFontNumber < 0 || CurFontNumber >= MAX_FONTS)
    Fatal ("ChangeFontAndSetup(): illegal font number.");

  CurFontPointer = Fonts[CurFontNumber];
  if (CurFontPointer == NULL)
    Fatal ("ChangeFontAndSetup(): undefined font.");
  basis = CurFontPointer->f_s / 6;

  ThresholdMovementHP =  1 * basis; /* [84] of dvitype */
  ThresholdMovementHN = -4 * basis;
  ThresholdMovementVP =  5 * basis;
  ThresholdMovementVN = -5 * basis;
  PssFlushStringAndPos();
  PssSendCommand (CurFontPointer->f_sf);

#ifdef DEBUG
  fprintf (stderr, "Font: %s, HP: %d, HN: %d, VP: %d, VN: %d\n",
	   CurFontPointer->f_ex_file.ef_fn,
	   PixRound(ThresholdMovementHP, HConv),
	   PixRound(ThresholdMovementHN, HConv),
	   PixRound(ThresholdMovementVP, HConv),
	   PixRound(ThresholdMovementVN, HConv));
#endif
}

/*
 * MaxDriftH
 * *********
 * Check, whether the maxdrift in h has been exceeded.
 * The amount of correction is in most cases one pixel, occasionally two.
 * The correction, if any, is accumulated into AccDeltaH.
 *
 * This procedure is called from the following places:
 *   1. MoveH
 *   2. SetPutChar
 *   3. SetRule
 * RETURN: FALSE: no correction was necessary.
 *         TRUE:  correction was necessary: the correction
 *         is made and accumulated in AccDeltaH.
 */
int
MaxDriftH()
{
  register DVIU tmp;
  register DVIU diff;

  diff = h - hh; /* Printer position is diff_h DVIUs off the DVI file
		    position.
		    Printer is to the left if > 0.
		    Printer is to the right if < 0. */

  /* Return if within boundaries (inclusive). */
  if (MaxDriftHorizontalNeg <= diff && diff <= MaxDriftHorizontal)
    return (FALSE);

  MaxDriftHCount++;

  if (diff > MaxDriftHorizontal) {
    /* Correction here for printer too far to the left. */
    tmp = ((diff-MaxDriftHorizontal) + (HConv-1)) / HConv;
    AccDeltaH += tmp;
    hh += tmp * HConv;
#ifdef MAX_DRIFT_EXTRA_CHECK
    if (tmp < 0 || tmp > MAX_DRIFT)
      Fatal ("MaxDriftH() - 1");
    fprintf (stderr, "MaxDriftH, Pos, %d\n", MaxDriftHCount);
#endif
    return (TRUE);
  }

  if (diff < MaxDriftHorizontalNeg) {
    /* Correction here for printer too far to the right. */
    tmp = ((MaxDriftHorizontalNeg-diff) + (HConv-1)) / HConv;
    AccDeltaH -= tmp;
    hh -= tmp * HConv;
#ifdef MAX_DRIFT_EXTRA_CHECK
    if (tmp < 0 || tmp > MAX_DRIFT)
      Fatal ("MaxDriftH() - 2");
    fprintf (stderr, "MaxDriftH, Neg, %d\n", MaxDriftHCount);
#endif
    return (TRUE);
  }

  Fatal ("MaxDriftH(): should never come here.");
  return(0); /* To make lint shut up. */
}

/*
 * MaxDriftV
 * *********
 * Check, whether the maxdrift in v has been exceeded.
 * RETURN: FALSE -- no correction was necessary
 *         TRUE  -- correction necessary, make correction
 * The correction is accumulated into AccDeltaV.
 */
int
MaxDriftV()
{
  register DVIU tmp;
  register DVIU diff;

  diff = v - vv; /* Printer position is diff DVIUs from
		    current position. If > 0 it's below. */

  /* Return if within boundaries (inclusive) */
  if (MaxDriftVerticalNeg <= diff && diff <= MaxDriftVertical)
    return (FALSE);

  MaxDriftVCount++;

  if (diff > MaxDriftVertical) {
    /* Correction goes here if printer too far below. */
    tmp = ((diff-MaxDriftVertical) + (VConv-1)) / VConv;
    AccDeltaV += tmp;
    vv += tmp * VConv;
#ifdef MAX_DRIFT_EXTRA_CHECK
    if (tmp < 0 || tmp > MAX_DRIFT)
      Fatal ("MaxDriftV() - 1");
    fprintf (stderr, "MaxDriftV, Pos, %d\n", MaxDriftVCount);
#endif
    return (TRUE);
  }

  if (diff < MaxDriftVerticalNeg) {
    /* Correction goes here if printer too far above. */
    tmp = ((MaxDriftVerticalNeg-diff) + (VConv-1)) / VConv;
    AccDeltaV -= tmp;
    vv -= tmp * VConv;
#ifdef MAX_DRIFT_EXTRA_CHECK
    if (tmp < 0 || tmp > MAX_DRIFT)
      Fatal ("MaxDriftV() - 2");
    fprintf (stderr, "MaxDriftV, Neg, %d\n", MaxDriftVCount);
#endif
    return (TRUE);
  }

  Fatal ("MaxDriftV(): should never come here");
  return(0); /* To make lint shut up. */
}

/*
 * MoveH
 * *****
 * Move horizontally, either relative or absolute, depending
 * on the amount of the movement. The movement itself is
 * not sent to the printer but saved in AccDeltaH.
 *
 * delta: the amount, by which you want to move in DVIUS.
 */
void
MoveH(delta)
     DVIU delta;
{
  register PXLU diff_h;

#ifdef POSITIONING_TESTING
  PrintPositions ("MoveH/1");
  fprintf (EX_FP(ExPosFile), "\tMoveH: delta = %d\n", delta);
#endif
  h += delta;
  if ((delta > ThresholdMovementHN) && (delta < ThresholdMovementHP) && (!AllMovementsAbsolute)) {
    diff_h = PixRound (delta, HConv); /* Relative movement */
    AccDeltaH += diff_h;
    hh += diff_h*HConv; 
    (void)MaxDriftH();
#ifdef POSITIONING_TESTING
    fprintf (EX_FP(ExPosFile), "\tdelta = %d, relative, diff = %d\n", delta, diff_h);
#endif
  } else { /* Absolute */
    diff_h = PixRound(h-hh, HConv);
    AccDeltaH += diff_h;
    hh += diff_h*HConv;
#ifdef POSITIONING_TESTING
    fprintf (EX_FP(ExPosFile), "\tdelta = %d, absolute, diff = %d\n", delta, diff_h);
#endif
  }
#ifdef POSITIONING_TESTING
  PrintPositions ("MoveH/2");
#endif
}

/*
 * MoveV
 * *****
 * Move vertically, either relative or absolute, depending
 * on the amount of the movement. The movement itself is not
 * done but saved in AccDeltaV.
 *
 * delta: the amount, by which we want to move.
 */
void
MoveV(delta)
     DVIU delta;
{
  register PXLU diff_v;

  v += delta;
  if ((delta > ThresholdMovementVN) && (delta < ThresholdMovementVP) && (!AllMovementsAbsolute)) {
    diff_v = PixRound (delta, VConv); /* relative */
    AccDeltaV += diff_v;
    vv += diff_v*VConv; 
    (void)MaxDriftV();
  } else { /* absolute */
    diff_v = PixRound(v-vv, VConv);
    AccDeltaV += diff_v;
    vv += diff_v*VConv;
  }
}

/*
 * PixRound
 * ********
 * Round a value in DVIUs to pixels.
 *
 * val: value in DVIU
 * conv: conversion factor
 * RET: the rounded value in pixels.
 */
PXLU
PixRound (val, conv)
     DVIU val;
     int conv;
{
  int ret;

  if (val<0)
    ret = (val-(conv/2))/conv;
  else
    ret = (val+(conv/2))/conv;
  return (ret);
}

/*
 * SetPutChar
 * **********
 * This routine is called by SET1..4 and PUT1..4

 * c: the character code.
 * control: 0: SetChar
 *          1: PutChar
 */
void
SetPutChar(c, control)
     int c, control;
{
  CE_P ce;

  /* Write any remaining stuff out. */
  PssFlushStringAndPos();

  switch (CurFontPointer->f_type) {
    case CF_PXL:
    case CF_GF:
    case CF_PK:
      PssSendInteger(c);
      if (control == 0) {
	EMIT_SCC('u');
      } else {
	EMIT_SCC('v');
      }
      break;

    /* PS fonts: we may have a PS emulated character now. */
    case CF_PDR:
      switch (CurFontPointer->f_ch[c].c_type) {
        case CT_NONE:
	  Fatal ("SetChar(): CF_PDR CT_NONE");
	case CT_ASS:
	case CT_AFM:
	  PssSendInteger(c);
	  if (control == 0) {
	    EMIT_SCC('u');
	  } else {
	    EMIT_SCC('v');
	  }
	  break;
	case CT_EXECPS:
	  PssFlushStringAndPos();
	  PssSendCommand (CurFontPointer->f_ch[c].c_n);
	  break;
	default:
	  Fatal ("SetPutChar(): CF_PDR/def");
      } /* switch according to character type within PS font */
      break; /* end PS fonts */
    default: Fatal ("SetPutChar(): E-1");
  } /* switch according to font type */

  if (control == 0) {
    ce = &(CurFontPointer->f_ch[c]);
    h  += ce->c_w_tfm;
    hh += ce->c_rw;
    (void)MaxDriftH();
  }
}

/*
 * SetRule
 * *******
 * Typeset a rule
 *
 * a: height of the rule
 * b: width of the rule
 * code: dvi file command which caused that rule to be typeset
 *        (SET_RULE or PUT_RULE)
 */
void
SetRule (a, b, code)
     DVIU	a, b;
     int	code;
{
#ifdef POSITIONING_TESTING
  if (code == DVI_SET_RULE)
    PrintPositions ("SET_RULE/1");
  if (code == DVI_PUT_RULE)
    PrintPositions ("PUT_RULE/2");
  fprintf (EX_FP(ExPosFile), "\tDimensions: a: %7d, b: %7d\n", a, b);
#endif

  PssFlushStringAndPos();
  if (a > 0 && b > 0) {
#ifdef DEBUG
    fprintf (stderr, "%% Size of rule: %8.3lf by %8.3lf\n",
	     ConvertPosPoints(a), ConvertPosPoints(b));
#endif
    PssSendInteger(PixRound(b,HConv));
    PssSendInteger(-PixRound(a,VConv));
    EMIT_SCC ('z');
  }
  
  if (code == DVI_SET_RULE) { /* Print rule and move! */
    MoveH(b);
    (void)MaxDriftH();
  }
#ifdef POSITIONING_TESTING
  if (code == DVI_SET_RULE)
    PrintPositions ("SET_RULE/2");
  if (code == DVI_PUT_RULE)
    PrintPositions ("PUT_RULE/2");
#endif
}

/*
 * SetString
 * *********
 * Called in Pass1() with the first character of a string to
 * be printed already read in. This character is provided as argument
 * to this routine so it is not necessary to read that character again.
 * If the string is longer than 60 characters, the string is broken up
 * by a premature return from this procedure (which leads to a more
 * or less immediate call of this procedure again).
 *
 * firstch: the first character (already read in) of the string to be printed.
 */
void
SetString(firstch)
     int firstch;
{
  int  c; /* Character we get from file. */
  CE_P ce_p; /* Pointer to character structure. */
  int pdr_slitex; /* Flag: Invisible SliTex PostScript font */
  int lcc; /* Local character count. */

#ifdef POSITIONING_TESTING
  char tmp[256];
#endif

  PssFlushStringAndPos(); /* Send new position if necessary. */

  pdr_slitex = FALSE;
  c = firstch; /* Character being read in. */
  lcc = 1; /* Local character count: already one character provided. */

  for (;;) {
#ifdef DEBUG
    CommandOffsetPositioning = FExTell(&ExDvi);
    fprintf (stderr, "command offset: %d\n", CommandOffsetPositioning);
    fflush (stderr);
#endif

#ifdef POSITIONING_TESTING
    sprintf (tmp, "SETC %d", c-DVI_SETC_000);
    PrintPositions(tmp, CommandOffsetPositioning);
#endif
    /* c: character to print. Print it now. */
    ce_p = &(CurFontPointer->f_ch[c]);

    /* Printing stuff depends on the font type etc. */
    switch (CurFontPointer->f_type) {
      case CF_PXL:
      case CF_GF:
      case CF_PK:
#ifdef DEBUG
        fprintf (stderr, "Counter: %d\n", PssStringIndex);
	fflush (stderr);
#endif
        PSS_ADD_CHAR (c);
	break;

      /* PS fonts: we may have a PS emulated character now. */
      case CF_PDR:
	if (! CurFontPointer->f_pdr->p_i_slitex) {
	  /* Regular (non SliTeX) font */
	  switch (ce_p->c_type) {
	    case CT_NONE:
	      Fatal ("SetString(): CF_PDR CT_NONE");
	    case CT_ASS:
	    case CT_AFM:
	      PSS_ADD_CHAR (c);
	      break;
	    case CT_EXECPS:
	      PssFlushStringAndPos();
	      PssSendCommand (ce_p->c_n);
	      break;
	    default:
	      Fatal ("SetString(): CF_PDR/def");
	    } /* Switch according to character type within PS font. */
	} else {
	  pdr_slitex = TRUE;
	  /* Slitex font / character: just move to the right. */
	  switch (ce_p->c_type) {
	    case CT_NONE:
	      Fatal ("SetString(): CF_PDR CT_NONE 2");
	    case CT_ASS:
	    case CT_AFM:
	    case CT_EXECPS:
	      MoveH(ce_p->c_w_tfm);
	      break;
	    default:
	      Fatal ("SetString(): CF_PDR/def 2");
	    } /* Switch according to character type within PS font. */
	}
	break; /* End PS fonts */

      default: Fatal ("SetChar(): E-1");
    } /* Switch according to font type. */

    /* Update position now: positing already done for slitex characters */
    if (! pdr_slitex) {
      /* Update positions: same for all cases, except for slitex characters
	 where the positioning was done before. */
      h += ce_p->c_w_tfm;
      hh+= ce_p->c_rw;
      if (MaxDriftH())
	PssFlushStringAndPos();
    }

    /* Get the next 'command': if it's not a character stop. */
    if ((c = NoSignExtend(EX_FP(ExDvi), 1)) > DVI_SETC_127 || c < DVI_SETC_000 ||
	lcc++ > LCC_MAX) {
      /* Backup: <command just read must be read in again in pass1.
	 Note that no output to the PostScript file takes place. This is
	 triggered by one of the following commands in the dvi file. */
      FExSeek (&ExDvi, -1, FSEEK_REL);
#ifdef DEBUG
      fprintf (stderr, "Command code for back up: %d\n", c);
#endif
      return;
    }
#ifdef DEBUG
    fprintf (stderr, "SetString(): command: %d\n", c);
#endif
  } /* for (;;) */
}

/*
 * WarningTfmVersusPxlWidth
 * ************************
 * Generate a warning message, if for a given character
 * the tfm width and the pixel width are off by more than one pixel.
 *
 * code: its code.
 * ce_p: character entry pointer.
 */
void
WarningTfmVersusPxlWidth(code, ce_p)
     int code;
     CE_P ce_p;
{
  int diff_dvius;
  int diff_px;

  if (!MaxPixelsWarning)
    return;

  diff_dvius = ABS_MACRO(ce_p->c_w_tfm - ce_p->c_rw);
  diff_px =    PixRound(diff_dvius, HConv);

  if (diff_px <= MAX_PIXELS_TFM_RW)
    return;

  fprintf (stderr, "WarningTfmVersusPxlWidth(): [%s], char '%o\n", CurFontPointer->f_n, code);
  fprintf (stderr, "\ttfm width: %d, real width: %d, diff(pixels): %d\n",
	   ce_p->c_w_tfm, ce_p->c_rw, diff_px);
}

#ifdef POSITIONING_TESTING
int PosCount = 0;

/*
 * PrintPositions
 * **************
 * Print positioning information.
 *
 * s: identifier string.
 */
void
PrintPositions(s)
     char *s;
{
  if (PosCount % 10 == 0)
    fprintf (EX_FP(ExPosFile), "  SN   id  offs            h          hh     hh-h         v        vv       vv-v\n");
  PosCount++;
  fprintf (EX_FP(ExPosFile), "%4d %-10s %5d %10d %10d (%5d) %6d %10d %10d %6d\n",
	   PosCount, s, CommandOffsetPositioning, h, hh, PixRound (hh, HConv),
	   hh-h, v, vv, vv-v);
}

/*
 * PositioningSingleCharacterCommand
 * *********************************
 * This procedure when called does some after `single
 * character command processing'.
 */
int
PositioningSingleCharacterCommand()
{
  EMIT_NEW_LINE;
  EMIT_1("PrintPosition\n");
}
#endif