/*
	WARNING: This file was generated by dkct.
	Changes you make here will be lost if dkct is run again!
	You should modify the original source and run dkct on it.
	Original source: f2ludpat.ctr
*/

/*
Copyright (C) 2012-2013, Dirk Krause

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice,
  this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above opyright 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 author nor the names of contributors may be used
  to endorse or promote products derived from this software without specific
  prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

/**	@file f2ludpat.c The f2ludpat module.
*/


#line 36 "f2ludpat.ctr"

#include "dk3all.h"
#include "dk3bezcu.h"
#include "fig2lat.h"
#include "f2lud.h"
#include "f2lsvg.h"
#include "f2lpgf.h"
#include "f2lpdf.h"
#include "f2leps.h"
#include "dk3figto.h"
#include "dkt-version.h"
#include "f2ludpat.h"





#line 52 "f2ludpat.ctr"



/**	One falling line.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	y0	Y value at x=0.
	@param	m	Tangens alpha.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_one_falling_line(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  double		 y0,
  double		 m,
  int			*ec
)
{
  double	xs;	/* Start point x. */
  double	ys;	/* Start point y. */
  double	xe;	/* End point x. */
  double	ye;	/* End point y. */
  int		hs = 0;	/* Flag: Have start point. */
  int		he = 0;	/* Flag: Have end point. */

  ys = dk3ma_d_sub_ok(y0, dk3ma_d_mul_ok(m, outbb->xmin, ec), ec);
  if(ys > outbb->ymin) {
    if(ys <= outbb->ymax) {
      xs = outbb->xmin; hs = 1;
    } else {
      ys = outbb->ymax;
      xs = dk3ma_d_div_ok(dk3ma_d_sub_ok(y0, outbb->ymax, ec), m, ec);
      if(xs < outbb->xmax) {
        hs = 1;
      }
    }
    ye = dk3ma_d_sub_ok(y0, dk3ma_d_mul_ok(m, outbb->xmax, ec), ec);
    if(ye < outbb->ymax) {
      if(ye < outbb->ymin) {
        ye = outbb->ymin;
	xe = dk3ma_d_div_ok(dk3ma_d_sub_ok(y0, outbb->ymin, ec), m, ec);
	if(xe > outbb->xmin) {
	  he = 1;
	}
      } else {
        xe = outbb->xmax; he = 1;
      }
    }
    if((hs) && (he)) {
      f2lud_newpath(job, drw, obj);
      f2lud_moveto(job, drw, obj, xs, ys);
      f2lud_lineto(job, drw, obj, xe, ye);
      f2lud_stroke(job, drw, obj);
    }
  }
}



/**	One rising line.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	y0	Y value at x=0.
	@param	m	Tangens alpha.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_one_rising_line(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  double		 y0,
  double		 m,
  int			*ec
)
{
  double	xs;	/* Start point x. */
  double	ys;	/* Start point y. */
  double	xe;	/* End point x. */
  double	ye;	/* End point y. */
  int		hs = 0;	/* Flag: Have start point. */
  int		he = 0;	/* Flag: Have end point. */

  ye = dk3ma_d_add_ok(
    y0,
    dk3ma_d_mul_ok(m, outbb->xmax, ec),
    ec
  );
  if(ye > outbb->ymin) {
    if(ye <= outbb->ymax) {
      xe = outbb->xmax; he = 1;
    } else {
      ye = outbb->ymax;
      xe = dk3ma_d_div_ok(dk3ma_d_sub_ok(outbb->ymax, y0, ec), m, ec);
      if((xe > outbb->xmin) && (xe < outbb->xmax)) {
        he = 1;
      }
    }
    if(he) {
      ys = dk3ma_d_add_ok(
        y0,
	dk3ma_d_mul_ok(m, outbb->xmin, ec),
	ec
      );
      if(ys < outbb->ymax) {
        if(ys >= outbb->ymin) {
	  xs = outbb->xmin; hs = 1;
	} else {
	  ys = outbb->ymin;
	  xs = dk3ma_d_div_ok(dk3ma_d_sub_ok(outbb->ymin, y0, ec), m, ec);
	  if((xs > outbb->xmin) && (xs < outbb->xmax)) {
	    hs = 1;
	  }
	}
      }
    }
    if((hs) && (he)) {
      f2lud_newpath(job, drw, obj);
      f2lud_moveto(job, drw, obj, xs, ys);
      f2lud_lineto(job, drw, obj, xe, ye);
      f2lud_stroke(job, drw, obj);
    }
  }
}



/**	Falling lines.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	dy	Y step.
	@param	m	Tangens alpha.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_falling_lines(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  double		 dy,
  double		 m,
  int			*ec
)
{
  double	ys;	/* Start y. */
  double	ye;	/* End y. */
  double	y;	/* Current y. */

  ys = dk3ma_d_add_ok(
    outbb->ymin,
    dk3ma_d_mul_ok(m, outbb->xmin, ec),
    ec
  );
  ye = dk3ma_d_add_ok(
    outbb->ymax,
    dk3ma_d_mul_ok(m, outbb->xmax, ec),
    ec
  );
  ys = dk3ma_d_mul_ok(
    dy,
    floor(dk3ma_d_div_ok(ys, dy, ec)),
    ec
  );
  y = ys;
  while(y < ye) {
    f2ludpat_one_falling_line(job, drw, obj, outbb, y, m, ec);
    y = dk3ma_d_add_ok(y, dy, ec);
  }
}



/**	Rising lines.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	dy	Y step.
	@param	m	Tangens alpha.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_rising_lines(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  double		 dy,
  double		 m,
  int			*ec
)
{
  double	ys;	/* Start y. */
  double	ye;	/* End y. */
  double	y;	/* Current y. */

  ys = dk3ma_d_sub_ok(
    outbb->ymin,
    dk3ma_d_mul_ok(m, outbb->xmax, ec),
    ec
  );
  ye = dk3ma_d_sub_ok(
    outbb->ymax,
    dk3ma_d_mul_ok(m, outbb->xmin, ec),
    ec
  );
  ys = dk3ma_d_mul_ok(
    dy,
    floor(dk3ma_d_div_ok(ys, dy, ec)),
    ec
  );
  y = ys;
  while(y < ye) {
    f2ludpat_one_rising_line(job, drw, obj, outbb, y, m, ec);
    y = dk3ma_d_add_ok(y, dy, ec);
  }
}



/**	30 degree falling lines.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_30_falling_lines(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  f2ludpat_falling_lines(
    job, drw, obj, outbb,
    dk3ma_d_div_ok(3.6, cos(M_PI / 6.0), ec),
    (1.0 / sqrt(3.0)),
    ec
  );
}



/**	30 degree rising lines.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_30_rising_lines(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  f2ludpat_rising_lines(
    job, drw, obj, outbb,
    dk3ma_d_div_ok(3.6, cos(M_PI / 6.0), ec),
    (1.0 / sqrt(3.0)),
    ec
  );
}



/**	45 degree falling lines.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_45_falling_lines(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  f2ludpat_falling_lines(job, drw, obj, outbb, (3.6 * sqrt(2.0)), 1.0, ec);
}



/**	45 degree rising lines.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_45_rising_lines(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  f2ludpat_rising_lines(job, drw, obj, outbb, (3.6 * sqrt(2.0)), 1.0, ec);
}



/**	Horizontal bricks.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_horizontal_bricks(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  double		x;	/* Current x. */
  double		y;	/* Current y. */
  double		ys;	/* Start y. */
  double		xs;	/* Start x. */
  double		dy;	/* Y delta. */
  double		dx;	/* X delta. */
  int			lineno;	/* Flag: Odd (1) or even (0) line. */

  dy =  7.2;
  dx = 14.4;
  ys = outbb->ymin;
  xs = outbb->xmin;
  lineno = 0;
  ys = dk3ma_d_mul_ok(
    (2.0 * dy),
    floor(dk3ma_d_div_ok(ys, (2.0 * dy), ec)),
    ec
  );
  y = ys;
  while(y < outbb->ymax) {
    f2lud_newpath(job, drw, obj);
    f2lud_moveto(job, drw, obj, outbb->xmin, y);
    f2lud_lineto(job, drw, obj, outbb->xmax, y);
    f2lud_stroke(job, drw, obj);
    x = dk3ma_d_add_ok(xs, (((lineno) ? 0.75 : 0.25) * dx), ec);
    while(x < outbb->xmax) {
      f2lud_newpath(job, drw, obj);
      f2lud_moveto(job, drw, obj, x, y);
      f2lud_lineto(job, drw, obj, x, dk3ma_d_add_ok(y, dy, ec));
      f2lud_stroke(job, drw, obj);
      x = dk3ma_d_add_ok(x, dx, ec);
    }
    y = dk3ma_d_add_ok(y, dy, ec);
    lineno++;
    if(lineno > 1) { lineno = 0; }
  }
}



/**	Vertical bricks.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_vertical_bricks(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  double		x;	/* Current x value. */
  double		y;	/* Current y value. */
  double		xs;	/* Start x. */
  double		ys;	/* Start y. */
  double		dx;	/* Delta x. */
  double		dy;	/* Delta y. */
  int			lineno;	/* Flag: Odd (1) or even (0) line. */

  lineno = 0;
  dy = 14.4;
  dx =  7.2;
  xs = outbb->xmin;
  xs = dk3ma_d_mul_ok(
    (2.0 * dx),
    floor(dk3ma_d_div_ok(xs, (2.0 * dx), ec)),
    ec
  );
  ys = outbb->ymin;
  ys = dk3ma_d_mul_ok(
    dy,
    floor(dk3ma_d_div_ok(ys, dy, ec)),
    ec
  );
  x = xs;
  while(x < outbb->xmax) {
    x = dk3ma_d_add_ok(x, dx, ec);
    f2lud_newpath(job, drw, obj);
    f2lud_moveto(job, drw, obj, x, outbb->ymin);
    f2lud_lineto(job, drw, obj, x, outbb->ymax);
    f2lud_stroke(job, drw, obj);
    y = dk3ma_d_add_ok(ys, (((lineno) ? 0.75 : 0.25) * dy), ec);
    while(y < outbb->ymax) {
      f2lud_newpath(job, drw, obj);
      f2lud_moveto(job, drw, obj, x, y);
      f2lud_lineto(job, drw, obj, dk3ma_d_add_ok(x, dx, ec), y);
      f2lud_stroke(job, drw, obj);
      y = dk3ma_d_add_ok(y, dy, ec);
    }
    lineno++;
    if(lineno > 1) { lineno = 0; }
  }
}



/**	Horizontal lines.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_horizontal_lines(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  double		y;	/* Current y. */
  double		ys;	/* Start y. */
  double		dy;	/* Delta y per pass. */

  dy = 3.6;
  ys = outbb->ymin;
  ys = dk3ma_d_mul_ok(
    dy,
    floor(dk3ma_d_div_ok(ys, dy, ec)),
    ec
  );
  y = ys;
  while(y < outbb->ymax) {
    f2lud_newpath(job, drw, obj);
    f2lud_moveto(job, drw, obj, outbb->xmin, y);
    f2lud_lineto(job, drw, obj, outbb->xmax, y);
    f2lud_stroke(job, drw, obj);
    y = dk3ma_d_add_ok(y, dy, ec);
  }
}



/**	Vertical lines.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_vertical_lines(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  double		x;	/* Current x. */
  double		xs;	/* Start x. */
  double		dx;	/* Delta x. */

  dx = 3.6;
  xs = outbb->xmin;
  xs = dk3ma_d_mul_ok(
    dx,
    floor(dk3ma_d_div_ok(xs, dx, ec)),
    ec
  );
  x = xs;
  while(x < outbb->xmax) {
    f2lud_newpath(job, drw, obj);
    f2lud_moveto(job, drw, obj, x, outbb->ymin);
    f2lud_lineto(job, drw, obj, x, outbb->ymax);
    f2lud_stroke(job, drw, obj);
    x = dk3ma_d_add_ok(x, dx, ec);
  }
}



/**	Horizontal tire treads.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_horizontal_tire_treads(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  double	x;	/* Current x. */
  double	y;	/* Current y. */
  double	dx;	/* Delta x per step. */
  double	dy;	/* Delta y per pass. */
  double	xs;	/* Start x. */
  double	ys;	/* Start y. */

  dy = 7.2;
  dx = 3.6;
  xs = outbb->xmin; ys = outbb->ymin;
  xs = dk3ma_d_mul_ok(
    dy,
    floor(dk3ma_d_div_ok(xs, dy, ec)),
    ec
  );
  ys = dk3ma_d_mul_ok(
    dy,
    floor(dk3ma_d_div_ok(ys, dy, ec)),
    ec
  );
  y = ys;
  while(y < outbb->ymax) {
    x = xs;
    f2lud_newpath(job, drw, obj);
    f2lud_moveto(job, drw, obj, x, y);
    f2lud_lineto(
      job, drw, obj,
      dk3ma_d_add_ok(x, dx, ec), dk3ma_d_add_ok(y, dx, ec)
    );
    f2lud_lineto(
      job, drw, obj,
      dk3ma_d_add_ok(x, dy, ec), y
    );
    x = dk3ma_d_add_ok(x, dy, ec);
    while(x < outbb->xmax) {
      f2lud_lineto(
        job, drw, obj,
        dk3ma_d_add_ok(x, dx, ec), dk3ma_d_add_ok(y, dx, ec)
      );
      f2lud_lineto(
        job, drw, obj,
        dk3ma_d_add_ok(x, dy, ec), y
      );
      x = dk3ma_d_add_ok(x, dy, ec);
    }
    f2lud_stroke(job, drw, obj);
    y = dk3ma_d_add_ok(y, dy, ec);
  }
}



/**	Vertical tire treads.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_vertical_tire_treads(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  double	x;	/* Current x. */
  double	y;	/* Current y. */
  double	dx;	/* Delta x per pass. */
  double	dy;	/* Delta y per step. */
  double	xs;	/* Start x. */
  double	ys;	/* Start y. */

  dx = 7.2;
  dy = 3.6;
  xs = outbb->xmin; ys = outbb->ymin;
  xs = dk3ma_d_mul_ok(
    dy,
    floor(dk3ma_d_div_ok(xs, dy, ec)),
    ec
  );
  ys = dk3ma_d_mul_ok(
    dy,
    floor(dk3ma_d_div_ok(ys, dy, ec)),
    ec
  );
  x = xs;
  while(x < outbb->xmax) {
    y = ys;

    f2lud_newpath(job, drw, obj);
    f2lud_moveto(job, drw, obj, x, y);
    f2lud_lineto(job, drw, obj,
      dk3ma_d_add_ok(x, dy, ec), dk3ma_d_add_ok(y, dy, ec)
    );
    f2lud_lineto(job, drw, obj,
      x, dk3ma_d_add_ok(y, dx, ec)
    );
    y = dk3ma_d_add_ok(y, dx, ec);
    while(y < outbb->ymax) {
      f2lud_lineto(job, drw, obj,
        dk3ma_d_add_ok(x, dy, ec), dk3ma_d_add_ok(y, dy, ec)
      );
      f2lud_lineto(job, drw, obj,
        x, dk3ma_d_add_ok(y, dx, ec)
      );
      y = dk3ma_d_add_ok(y, dx, ec);
    }
    f2lud_stroke(job, drw, obj);
    x = dk3ma_d_add_ok(x, dx, ec);
  }
}




/**	Circles.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_circles(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  dk3_fig_poly_point_t	p[12];	/* Points for circle around origin. */
  dk3_fig_poly_point_t	q[12];	/* Points shifted to the specified center. */
  double	x;		/* Current x. */
  double	y;		/* Current y. */
  double	dx;		/* Delta x. */
  double	dy;		/* Delta y. */
  double	xs;		/* Start x. */
  double	ys;		/* Start y. */
  double	r;		/* Circle radius. */
  size_t	i;		/* Index to traverse p and q. */

  r  = 7.2;
  dx = dy = 2.0 * r;
  xs = outbb->xmin; ys = outbb->ymin;
  xs = dk3ma_d_mul_ok(
    dx,
    floor(dk3ma_d_div_ok(xs, dx, ec)),
    ec
  );
  ys = dk3ma_d_mul_ok(
    dy,
    floor(dk3ma_d_div_ok(ys, dy, ec)),
    ec
  );
  p[ 0].x = dx;
  p[ 0].y = r;
  p[ 1].x = dx;
  p[ 1].y = (1.0 + FIG2LAT_CIRCLE_QUADRANT_BEZIER) * r;
  p[ 2].x = (1.0 + FIG2LAT_CIRCLE_QUADRANT_BEZIER) * r;
  p[ 2].y = dx;
  p[ 3].x = r;
  p[ 3].y = dx;
  p[ 4].x = (1.0 - FIG2LAT_CIRCLE_QUADRANT_BEZIER) * r;
  p[ 4].y = dx;
  p[ 5].x = 0.0;
  p[ 5].y = (1.0 + FIG2LAT_CIRCLE_QUADRANT_BEZIER) * r;
  p[ 6].x = 0.0;
  p[ 6].y = r;
  p[ 7].x = 0.0;
  p[ 7].y = (1.0 - FIG2LAT_CIRCLE_QUADRANT_BEZIER) * r;
  p[ 8].x = (1.0 - FIG2LAT_CIRCLE_QUADRANT_BEZIER) * r;
  p[ 8].y = 0.0;
  p[ 9].x = r;
  p[ 9].y = 0.0;
  p[10].x = (1.0 + FIG2LAT_CIRCLE_QUADRANT_BEZIER) * r;
  p[10].y = 0.0;
  p[11].x = dx;
  p[11].y = (1.0 - FIG2LAT_CIRCLE_QUADRANT_BEZIER) * r;
  y = ys;
  while(y < outbb->ymax) {
    x = xs;
    while(x < outbb->xmax) {
      dk3mem_cpy((void *)q, (void *)p, sizeof(p));
      for(i = 0; i < 12; i++) {
        dk3fig_tool_shift_point(&(q[i]), x, y, ec);
      }
      f2lud_newpath(job, drw, obj);
      f2lud_moveto(job, drw, obj, q[0].x, q[0].y);
      f2lud_curveto(
        job, drw, obj, q[1].x, q[1].y, q[2].x, q[2].y, q[3].x, q[3].y
      );
      f2lud_curveto(
        job, drw, obj, q[4].x, q[4].y, q[5].x, q[5].y, q[6].x, q[6].y
      );
      f2lud_curveto(
        job, drw, obj, q[7].x, q[7].y, q[8].x, q[8].y, q[9].x, q[9].y
      );
      f2lud_curveto(
        job, drw, obj, q[10].x, q[10].y, q[11].x, q[11].y, q[0].x, q[0].y
      );
      f2lud_closepath(job, drw, obj);
      f2lud_stroke(job, drw, obj);
      x = dk3ma_d_add_ok(x, dx, ec);
    }
    y = dk3ma_d_add_ok(y, dy, ec);
  }
}



/**	Hexagons.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_hexagons(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  dk3_fig_poly_point_t	p[6];	/* Hexagon near origin. */
  dk3_fig_poly_point_t  q[6];	/* Hexagon shifted to current x, y. */
  double		r;	/* Radius. */
  double		y1;	/* Y position of help line. */
  double		x1;	/* X position of help line. */
  double		dy;	/* Delta y. */
  double		dx;	/* Delta x. */
  double		xs;	/* Start x. */
  double		ys;	/* Start y. */
  double		x;	/* Current x. */
  double		y;	/* Current y. */
  size_t		i;	/* Index to traverse p and q. */

  r  = 16.2 / (2.0 * sin(M_PI / 3.0));
  y1 = r * sin(M_PI / 3.0);
  x1 = r * (1.0 - cos(M_PI / 3.0));
  dx = 2.0 * (r + x1);
  dy = 2.0 * y1;
  xs = outbb->xmin;
  ys = outbb->ymin;
  xs = dk3ma_d_mul_ok(
    dx,
    floor(dk3ma_d_div_ok(xs, dx, ec)),
    ec
  );
  ys = dk3ma_d_mul_ok(
    dy,
    floor(dk3ma_d_div_ok(ys, dy, ec)),
    ec
  );
  p[0].x = 0.0;
  p[0].y = y1;
  p[1].x = x1;
  p[1].y = 0.0;
  p[2].x = x1 + r;
  p[2].y = 0.0;
  p[3].x = 2.0 * r;
  p[3].y = y1;
  p[4].x = p[2].x;
  p[4].y = 2.0 * y1;
  p[5].x = p[1].x;
  p[5].y = p[4].y;
  y = ys;
  while(y < outbb->ymax) {
    x = xs;
    while(x < outbb->xmax) {
      dk3mem_cpy((void *)q, (void *)p, sizeof(p));
      for(i = 0; i < 6; i++) {
        dk3fig_tool_shift_point(&(q[i]), x, y, ec);
      }
      f2lud_newpath(job, drw, obj);
      f2lud_moveto(job, drw, obj, q[0].x, q[0].y);
      f2lud_lineto(job, drw, obj, q[1].x, q[1].y);
      f2lud_lineto(job, drw, obj, q[2].x, q[2].y);
      f2lud_lineto(job, drw, obj, q[3].x, q[3].y);
      f2lud_lineto(job, drw, obj, q[4].x, q[4].y);
      f2lud_lineto(job, drw, obj, q[5].x, q[5].y);
      f2lud_lineto(job, drw, obj, q[0].x, q[0].y);
      f2lud_closepath(job, drw, obj);
      f2lud_stroke(job, drw, obj);
      f2lud_newpath(job, drw, obj);
      f2lud_moveto(job, drw, obj, q[3].x, q[3].y);
      f2lud_lineto(job, drw, obj, dk3ma_d_add_ok(q[3].x, r, ec), q[3].y);
      f2lud_stroke(job, drw, obj);
      x = dk3ma_d_add_ok(x, dx, ec);
    }
    y = dk3ma_d_add_ok(y, dy, ec);
  }
}



/**	Octagons.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_octagons(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  dk3_fig_poly_point_t	p[8];	/* Octagon near origin. */
  dk3_fig_poly_point_t	q[8];	/* Octagon shifted to final position. */
  double		dx;	/* Delta x. */
  double		dy;	/* Delta y. */
  double		xs;	/* Start x. */
  double		ys;	/* Start y. */
  double		x;	/* Current x. */
  double		y;	/* Current y. */
  double		l;	/* Factor for corner length. */
  double		x1;	/* X position of help line 1. */
  double		x2;	/* X position of help line 2. */
  size_t		i;	/* Index to traverse p and q. */

  dx = dy = 4.0 * 3.6;
  xs = outbb->xmin; ys = outbb->ymin;
  xs = dk3ma_d_mul_ok(
    dx,
    floor(dk3ma_d_div_ok(xs, dx, ec)),
    ec
  );
  ys = dk3ma_d_mul_ok(
    dy,
    floor(dk3ma_d_div_ok(ys, dy, ec)),
    ec
  );				

#line 948 "f2ludpat.ctr"
  l = dx / (1.0 + sqrt(2.0));	

#line 949 "f2ludpat.ctr"
  x1 = (dx - l) / 2.0;		

#line 950 "f2ludpat.ctr"
  x2 = x1 + l;			

#line 951 "f2ludpat.ctr"
  p[0].x = x1;			

#line 952 "f2ludpat.ctr"
  p[0].y = 0.0;			

#line 953 "f2ludpat.ctr"
  p[1].x = x2;			

#line 954 "f2ludpat.ctr"
  p[1].y = 0.0;			

#line 955 "f2ludpat.ctr"
  p[2].x = dx;			

#line 956 "f2ludpat.ctr"
  p[2].y = x1;			

#line 957 "f2ludpat.ctr"
  p[3].x = dx;			

#line 958 "f2ludpat.ctr"
  p[3].y = x2;			

#line 959 "f2ludpat.ctr"
  p[4].x = x2;			

#line 960 "f2ludpat.ctr"
  p[4].y = dy;			

#line 961 "f2ludpat.ctr"
  p[5].x = x1;			

#line 962 "f2ludpat.ctr"
  p[5].y = dy;			

#line 963 "f2ludpat.ctr"
  p[6].x = 0.0;			

#line 964 "f2ludpat.ctr"
  p[6].y = x2;			

#line 965 "f2ludpat.ctr"
  p[7].x = 0.0;			

#line 966 "f2ludpat.ctr"
  p[7].y = x1;			

#line 967 "f2ludpat.ctr"
  y = ys;
  while(y < outbb->ymax) {
    x = xs;
    while(x < outbb->xmax) {
      dk3mem_cpy((void *)q, (void *)p, sizeof(p));
      for(i = 0; i < 8; i++) {
        dk3fig_tool_shift_point(&(q[i]), x, y, ec);
      }
      f2lud_newpath(job, drw, obj);
      f2lud_moveto(job, drw, obj, q[0].x, q[0].y);
      f2lud_lineto(job, drw, obj, q[1].x, q[1].y);
      f2lud_lineto(job, drw, obj, q[2].x, q[2].y);
      f2lud_lineto(job, drw, obj, q[3].x, q[3].y);
      f2lud_lineto(job, drw, obj, q[4].x, q[4].y);
      f2lud_lineto(job, drw, obj, q[5].x, q[5].y);
      f2lud_lineto(job, drw, obj, q[6].x, q[6].y);
      f2lud_lineto(job, drw, obj, q[7].x, q[7].y);
      f2lud_lineto(job, drw, obj, q[0].x, q[0].y);
      f2lud_closepath(job, drw, obj);
      f2lud_stroke(job, drw, obj);
      x = dk3ma_d_add_ok(x, dx, ec);
    }
    y = dk3ma_d_add_ok(y, dy, ec);
  }
}



/**	Fish scale.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
	@param	points	Curve control points near origin.
	@param	dx	X delta.
	@param	dy	Y delta.
*/
static
void
f2ludpat_fish_scale(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec,
  dk3_fig_poly_point_t	*points,
  double		 dx,
  double		 dy
)
{
  dk3_fig_poly_point_t	q[7];	/* Points shifted to final position. */
  double	xs;		/* Start x. */
  double	ys;		/* Start y. */
  double	y1;		/* Y position of help line. */
  double	x;		/* Current x. */
  double	y;		/* Current y. */
  size_t	i;		/* Index to traverse npoints and q. */

  xs = outbb->xmin; ys = outbb->ymin;
  xs = dk3ma_d_mul_ok(
    dx,
    floor(dk3ma_d_div_ok(xs, dx, ec)),
    ec
  );
  ys = dk3ma_d_mul_ok(
    dy,
    floor(dk3ma_d_div_ok(ys, dy, ec)),
    ec
  );
  y = ys;
  while(y < outbb->ymax) {
    x = xs;
    while(x < outbb->xmax) {
      dk3mem_cpy((void *)q, (void *)points, sizeof(q));
      for(i = 0; i < 7; i++) {
        dk3fig_tool_shift_point(&(q[i]), x, y, ec);
      }
      f2lud_newpath(job, drw, obj);
      f2lud_moveto(job, drw, obj, q[0].x, q[0].y);
      f2lud_curveto(
        job, drw, obj,
	q[1].x, q[1].y, q[2].x, q[2].y, q[3].x, q[3].y
      );
      f2lud_curveto(
        job, drw, obj,
	q[4].x, q[4].y, q[5].x, q[5].y, q[6].x, q[6].y
      );
      f2lud_stroke(job, drw, obj);
      x = dk3ma_d_add_ok(x, dx, ec);
    }
    y1 = dk3ma_d_add_ok(y, 0.5 * dy, ec);
    x = dk3ma_d_sub_ok(xs, 0.5 * dx, ec);
    while(x < outbb->xmax) {
      dk3mem_cpy((void *)q, (void *)points, sizeof(q));
      for(i = 0; i < 7; i++) {
        dk3fig_tool_shift_point(&(q[i]), x, y1, ec);
      }
      f2lud_newpath(job, drw, obj);
      f2lud_moveto(job, drw, obj, q[0].x, q[0].y);
      f2lud_curveto(
        job, drw, obj,
	q[1].x, q[1].y, q[2].x, q[2].y, q[3].x, q[3].y
      );
      f2lud_curveto(
        job, drw, obj,
	q[4].x, q[4].y, q[5].x, q[5].y, q[6].x, q[6].y
      );
      f2lud_stroke(job, drw, obj);
      x = dk3ma_d_add_ok(x, dx, ec);
    }
    y = dk3ma_d_add_ok(y, dy, ec);
  }
}



/**	Large fish scale.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_large_fish_scale(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  dk3_fig_poly_point_t	p[7];	/* Curve points of segment near origin. */
  double		alpha;	/* Opening angle. */
  double		kappa;	/* Factor to construct Bezier control points. */
  double		pat;	/* Normal pattern distance. */
  double		dx;	/* Delta x. */
  double		dy;	/* Delta y. */
  double		r;	/* Fishscale radius. */
  double		as;	/* Start angle. */

  pat = 3.6;
  dx  = 4.0 * pat;
  dy  = 2.0 * pat;
  alpha = 0.9272952;	/* from iteration in Scilab */
  kappa = dk3fig_tool_arc_kappa(alpha, ec);
  r   = dk3ma_d_div_ok(pat, (1.0 - cos(alpha)), ec);
  as = 1.5 * M_PI - alpha;
  p[0].x = 0.0;
  p[0].y = pat;
  p[1].x = -1.0 * dk3ma_d_mul_ok(r, alpha, ec) * sin(as);
  p[1].y = dk3ma_d_mul_ok(r, alpha, ec) * cos(as);
  p[1].x = dk3ma_d_mul_ok(kappa, p[1].x, ec);
  p[1].y = dk3ma_d_mul_ok(kappa, p[1].y, ec);
  p[1].y = dk3ma_d_add_ok(p[1].y, p[0].y, ec);
  p[2].x = dk3ma_d_mul_ok(r, alpha, ec);
  p[2].x = dk3ma_d_mul_ok(p[2].x, kappa, ec);
  p[2].x = dk3ma_d_sub_ok(2.0 * pat, p[2].x, ec);
  p[2].y = 0.0;
  p[3].x = 2.0 * pat;
  p[3].y = 0.0;
  p[4].x = dk3ma_d_sub_ok(dx, p[2].x, ec);
  p[4].y = 0.0;
  p[5].x = dk3ma_d_sub_ok(dx, p[1].x, ec);
  p[5].y = p[1].y;
  p[6].x = dx;
  p[6].y = pat;
  f2ludpat_fish_scale(job, drw, obj, outbb, ec, p, dx, dy);
}




/**	Small fish scale.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_small_fish_scale(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  dk3_fig_poly_point_t	p[7];	/* Curve points of segment near origin. */
  double		pat;	/* Normal pattern distance. */
  double		dx;	/* Delta x. */
  double		dy;	/* Delta y. */

  pat = 3.6;
  p[0].x = 0.0;
  p[0].y = pat;
  p[1].x = 0.0;
  p[1].y = pat * (1.0 - FIG2LAT_CIRCLE_QUADRANT_BEZIER);
  p[2].x = p[1].y;
  p[2].y = 0.0;
  p[3].x = pat;
  p[3].y = 0.0;
  p[4].x = pat * (1.0 + FIG2LAT_CIRCLE_QUADRANT_BEZIER);
  p[4].y = 0.0;
  p[5].x = 2.0 * pat;
  p[5].y = p[1].y;
  p[6].x = p[5].x;
  p[6].y = pat;
  dx = 2.0 * pat;
  dy = 2.0 * pat;
  f2ludpat_fish_scale(job, drw, obj, outbb, ec, p, dx, dy);
}



/**	Horizontal shingles right.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_horizontal_shingles_right(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  double		pat;	/* Normal pattern distance. */
  double		x;	/* Current x. */
  double		y;	/* Current y. */
  double		xs;	/* Start x. */
  double		dy;	/* Start y. */
  double		dx;	/* Delta x. */
  int			lineno;	/* Flag: Odd (1) or even (0) line. */

  pat = 3.6;
  dy  = 2.0 * pat;
  dx  = 3.0 * dy;
  xs = outbb->xmin;
  xs = dk3ma_d_mul_ok(dx, floor(dk3ma_d_div_ok(xs, dx, ec)), ec);
  y  = outbb->ymin;
  y = dk3ma_d_mul_ok((3.0 * dy), floor(dk3ma_d_div_ok(y, (3.0 * dy), ec)), ec);
  lineno = 0;
  while(y < outbb->ymax) {
    f2lud_newpath(job, drw, obj);
    f2lud_moveto(job, drw, obj, outbb->xmin, y);
    f2lud_lineto(job, drw, obj, outbb->xmax, y);
    f2lud_stroke(job, drw, obj);
    x = xs;
    switch(lineno) {
      case 1: {
        x = dk3ma_d_add_ok(x, (2.0 * dy), ec);
      } break;
      case 2: {
        x = dk3ma_d_add_ok(x, dy, ec);
      } break;
    }
    while(x < outbb->xmax) {
      f2lud_newpath(job, drw, obj);
      f2lud_moveto(job, drw, obj, x, y);
      f2lud_lineto(
        job, drw, obj,
        dk3ma_d_add_ok(x, pat, ec), dk3ma_d_add_ok(y, dy, ec)
      );
      f2lud_stroke(job, drw, obj);
      x = dk3ma_d_add_ok(x, dx, ec);
    }
    y = dk3ma_d_add_ok(y, dy, ec);
    lineno++; if(lineno >= 3) { lineno = 0; }
  }
}



/**	Horizontal shingles left.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_horizontal_shingles_left(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  double		pat;	/* Normal pattern distance. */
  double		x;	/* Current x. */
  double		y;	/* Current y. */
  double		xs;	/* Start x. */
  double		dy;	/* Delta y. */
  double		dx;	/* Delta x. */
  int			lineno;	/* Flag: Odd (1) or even (0) line. */

  pat = 3.6;
  dy  = 2.0 * pat;
  dx  = 3.0 * dy;
  xs = outbb->xmin;
  xs = dk3ma_d_mul_ok(dx, floor(dk3ma_d_div_ok(xs, dx, ec)), ec);
  y  = outbb->ymin;
  y = dk3ma_d_mul_ok((3.0 * dy), floor(dk3ma_d_div_ok(y, (3.0 * dy), ec)), ec);
  lineno = 0;
  while(y < outbb->ymax) {
    f2lud_newpath(job, drw, obj);
    f2lud_moveto(job, drw, obj, outbb->xmin, y);
    f2lud_lineto(job, drw, obj, outbb->xmax, y);
    f2lud_stroke(job, drw, obj);
    x = xs;
    switch(lineno) {
      case 2: {
        x = dk3ma_d_add_ok(x, (2.0 * dy), ec);
      } break;
      case 1: {
        x = dk3ma_d_add_ok(x, dy, ec);
      } break;
    }
    while(x < outbb->xmax) {
      f2lud_newpath(job, drw, obj);
      f2lud_moveto(job, drw, obj, x, dk3ma_d_add_ok(y, dy, ec));
      f2lud_lineto( job, drw, obj, dk3ma_d_add_ok(x, pat, ec), y);
      f2lud_stroke(job, drw, obj);
      x = dk3ma_d_add_ok(x, dx, ec);
    }
    y = dk3ma_d_add_ok(y, dy, ec);
    lineno++; if(lineno >= 3) { lineno = 0; }
  }
}



/**	Vertical shingles falling.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_vertical_shingles_falling(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  double		x;	/* Current x. */
  double		y;	/* Current y. */
  double		pat;	/* Normal pattern distance. */
  double		dx;	/* Delta x. */
  double		dy;	/* Delta y. */
  double		ys;	/* Start y. */
  int			lineno;	/* Flag: Odd (1) or even (0) line. */

  pat = 3.6;
  dx  = 2.0 * pat;
  dy  = 3.0 * dx;

  ys = outbb->ymin;
  ys = dk3ma_d_mul_ok(dy, floor(dk3ma_d_div_ok(ys, dy, ec)), ec);
  x = outbb->xmin;
  x = dk3ma_d_mul_ok((3.0 * dx), floor(dk3ma_d_div_ok(x, (3.0 * dx), ec)), ec);
  lineno = 0;
  while(x < outbb->xmax) {
    f2lud_newpath(job, drw, obj);
    f2lud_moveto(job, drw, obj, x, outbb->ymin);
    f2lud_lineto(job, drw, obj, x, outbb->ymax);
    f2lud_stroke(job, drw, obj);
    y = ys;
    switch(lineno) {
      case 2: {
        y = dk3ma_d_add_ok(y, (2.0 * dx), ec);
      } break;
      case 1: {
        y = dk3ma_d_add_ok(y, dx, ec);
      } break;
    }
    while(y < outbb->ymax) {
      f2lud_newpath(job, drw, obj);
      f2lud_moveto(job, drw, obj, x, dk3ma_d_add_ok(y, pat, ec));
      f2lud_lineto(job, drw, obj, dk3ma_d_add_ok(x, dx, ec), y);
      f2lud_stroke(job, drw, obj);
      y = dk3ma_d_add_ok(y, dy, ec);
    }
    x = dk3ma_d_add_ok(x, dx, ec);
    lineno++; if(lineno >= 3) { lineno = 0; }
  }
}



/**	Vertical shingles rising.
	@param	job	Job structure.
	@param	drw	Drawing structure.
	@param	obj	Object requiring the fill pattern.
	@param	outbb	Bounding box to fill with pattern.
	@param	ec	Pointer to error code variable.
*/
static
void
f2ludpat_vertical_shingles_rising(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  dk3_bb_t		*outbb,
  int			*ec
)
{
  double		x;	/* Current x. */
  double		y;	/* Current y. */
  double		pat;	/* Normal pattern distance. */
  double		dx;	/* Delta x. */
  double		dy;	/* Delta y. */
  double		ys;	/* Start y. */
  int			lineno;	/* Flag: Odd (1) or even (0) line. */

  pat = 3.6;
  dx  = 2.0 * pat;
  dy  = 3.0 * dx;

  ys = outbb->ymin;
  ys = dk3ma_d_mul_ok(dy, floor(dk3ma_d_div_ok(ys, dy, ec)), ec);
  x = outbb->xmin;
  x = dk3ma_d_mul_ok((3.0 * dx), floor(dk3ma_d_div_ok(x, (3.0 * dx), ec)), ec);
  lineno = 0;
  while(x < outbb->xmax) {
    f2lud_newpath(job, drw, obj);
    f2lud_moveto(job, drw, obj, x, outbb->ymin);
    f2lud_lineto(job, drw, obj, x, outbb->ymax);
    f2lud_stroke(job, drw, obj);
    y = ys;
    switch(lineno) {
      case 2: {
        y = dk3ma_d_add_ok(y, dx, ec);
      } break;
      case 1: {
        y = dk3ma_d_add_ok(y, 2.0 * dx, ec);
      } break;
    }
    while(y < outbb->ymax) {
      f2lud_newpath(job, drw, obj);
      f2lud_moveto(job, drw, obj, x, y);
      f2lud_lineto(
        job, drw, obj,
	dk3ma_d_add_ok(x, dx, ec), dk3ma_d_add_ok(y, pat, ec)
      );
      f2lud_stroke(job, drw, obj);
      y = dk3ma_d_add_ok(y, dy, ec);
    }
    x = dk3ma_d_add_ok(x, dx, ec);
    lineno++; if(lineno >= 3) { lineno = 0; }
  }
}



void
f2lud_pattern(
  f2l_job_t		*job,
  dk3_fig_drawing_t	*drw,
  dk3_fig_obj_t		*obj,
  int			*ec
)
{
  dk3_bb_t		 mybb;		/* Bounding box of object. */
  dk3_bb_t		 outbb;		/* Box to fill. */
  double		 lw2;		/* Half line width. */

  dk3bb_reset(&mybb);
  dk3bb_reset(&outbb);
  if(dk3fig_prepare_obj_bb(&mybb, drw, obj, 1)) {
    dk3bb_add_x(&outbb, dk3ct_2d_x(&(job->ct2d), mybb.xmin, ec));
    dk3bb_add_x(&outbb, dk3ct_2d_x(&(job->ct2d), mybb.xmax, ec));
    dk3bb_add_y(&outbb, dk3ct_2d_y(&(job->ct2d), mybb.ymin, ec));
    dk3bb_add_y(&outbb, dk3ct_2d_y(&(job->ct2d), mybb.ymax, ec));
    lw2 = 0.45;
    if(job->lighten) { lw2 = 0.5 * lw2; }
    outbb.xmin = dk3ma_d_sub_ok(outbb.xmin, lw2, ec);
    outbb.xmax = dk3ma_d_add_ok(outbb.xmax, lw2, ec);
    outbb.ymin = dk3ma_d_sub_ok(outbb.ymin, lw2, ec);
    outbb.ymax = dk3ma_d_add_ok(outbb.ymax, lw2, ec);
    switch(obj->fi) {
      case 41: {
        f2ludpat_30_falling_lines(job, drw, obj, &outbb, ec);
      } break;
      case 42: {
        f2ludpat_30_rising_lines(job, drw, obj, &outbb, ec);
      } break;
      case 43: {
        f2ludpat_30_falling_lines(job, drw, obj, &outbb, ec);
	f2ludpat_30_rising_lines(job, drw, obj, &outbb, ec);
      } break;
      case 44: {
        f2ludpat_45_falling_lines(job, drw, obj, &outbb, ec);
      } break;
      case 45: {
        f2ludpat_45_rising_lines(job, drw, obj, &outbb, ec);
      } break;
      case 46: {
        f2ludpat_45_falling_lines(job, drw, obj, &outbb, ec);
	f2ludpat_45_rising_lines(job, drw, obj, &outbb, ec);
      } break;
      case 47: {
        f2ludpat_horizontal_bricks(job, drw, obj, &outbb, ec);
      } break;
      case 48: {
        f2ludpat_vertical_bricks(job, drw, obj, &outbb, ec);
      } break;
      case 49: {
        f2ludpat_horizontal_lines(job, drw, obj, &outbb, ec);
      } break;
      case 50: {
        f2ludpat_vertical_lines(job, drw, obj, &outbb, ec);
      } break;
      case 51: {
        f2ludpat_horizontal_lines(job, drw, obj, &outbb, ec);
	f2ludpat_vertical_lines(job, drw, obj, &outbb, ec);
      } break;
      case 52: {
        f2ludpat_horizontal_shingles_right(job, drw, obj, &outbb, ec);
      } break;
      case 53: {
        f2ludpat_horizontal_shingles_left(job, drw, obj, &outbb, ec);
      } break;
      case 54: {
        f2ludpat_vertical_shingles_falling(job, drw, obj, &outbb, ec);
      } break;
      case 55: {
        f2ludpat_vertical_shingles_rising(job, drw, obj, &outbb, ec);
      } break;
      case 56: {
	f2ludpat_large_fish_scale(job, drw, obj, &outbb, ec);
      } break;
      case 57: {
        f2ludpat_small_fish_scale(job, drw, obj, &outbb, ec);
      } break;
      case 58: {
        f2ludpat_circles(job, drw, obj, &outbb, ec);
      } break;
      case 59: {
        f2ludpat_hexagons(job, drw, obj, &outbb, ec);
      } break;
      case 60: {
        f2ludpat_octagons(job, drw, obj, &outbb, ec);
      } break;
      case 61: {
        f2ludpat_horizontal_tire_treads(job, drw, obj, &outbb, ec);
      } break;
      case 62: {
        f2ludpat_vertical_tire_treads(job, drw, obj, &outbb, ec);
      } break;
    }
  } else {		

#line 1535 "f2ludpat.ctr"
  }
}



