/* Copyright 1996 Acorn Computers Ltd
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/****************************************************************************
 * This source file was written by Acorn Computers Limited. It is part of   *
 * the RISCOS library for writing applications in C for RISC OS. It may be  *
 * used freely in the creation of programs for Archimedes. It should be     *
 * used with Acorn's C Compiler Release 3 or later.                         *
 *                                                                          *
 ***************************************************************************/

/*
 * Title:    drawmod.h
 * Purpose:  C interface to the Draw module
 *
 */


/*
 * This file provides an interface to the Draw module (not to be confused
 * with the !Draw application). It defines a number of types used for
 * PostScript-like operations (with enhancements). The enhancements consist
 * mainly of choice of fill style (fill including/excluding boundary etc),
 * extra winding numbers, differing "leading"/"trailing" line caps and
 * triangular line caps. It calls the Draw SWIs.
 *
 */

#ifndef __drawmod_h
#define __drawmod_h

#ifndef __os_h
#include "os.h"
#endif

/************************** Definition of a path **************************/

typedef enum
        {
          path_term      = 0,   /* end of path                  */
          path_ptr       = 1,   /* pointer to path continuation */
          path_move_2    = 2,   /* move to (x,y) -- new subpath */
                                /* affects winding numbers      */
          path_move_3    = 3,   /* move to (x,y) -- new subpath */
                                /* winding numbers unaffected   */
                                /* (used internally)            */
          path_closegap  = 4,   /* close current subpath with   */
                                /* a gap                        */
          path_closeline = 5,   /* close current subpath with   */
                                /* a line                       */
          path_bezier    = 6,   /* Bezier curve to (x3,y3) with */
                                /* control points at (x1,y1)    */
                                /* and (x2,y2)                  */
          path_gapto     = 7,   /* gap to (x,y), not starting   */
                                /* new subpath (used internally)*/
          path_lineto    = 8    /* line to (x,y)                */
        } drawmod_path_tagtype;

typedef struct                        /* end of path element */
        {
          drawmod_path_tagtype  tag;
          unsigned int  bytes_free;
        } drawmod_path_endstr;

typedef struct                        /* continuation ptr element */
        {
          drawmod_path_tagtype tag;
          void        *ptr;
        } drawmod_path_ptrstr;

typedef struct                        /* move2/move3 element */
        {
          drawmod_path_tagtype tag;
          int          x, y;
        } drawmod_path_movestr;

typedef struct                        /* close with gap element */
        {
          drawmod_path_tagtype tag;
        } drawmod_path_closegapstr;

typedef struct                        /* close with line element */
        {
          drawmod_path_tagtype tag;
        } drawmod_path_closelinestr;

typedef struct                        /* Bezier curve element */
        {
          drawmod_path_tagtype tag;
          int          x1,            /* control point (x1,y1) */
                       y1,
                       x2,            /* control point (x2,y2) */
                       y2,
                       x3,            /* end point (x3,y3)     */
                       y3;
        } drawmod_path_bezierstr;

typedef struct                        /* gap to (x,y) element */
        {
          drawmod_path_tagtype tag;
          int          x,y;
        } drawmod_path_gaptostr;

typedef struct                        /* line to (x,y) element */
        {
          drawmod_path_tagtype tag;
          int          x,y;
        } drawmod_path_linetostr;

typedef union                            /* pointer to a path element */
        {
          drawmod_path_endstr       *end;
          drawmod_path_ptrstr       *ptr;
          drawmod_path_movestr      *move2;
          drawmod_path_movestr      *move3;
          drawmod_path_closegapstr  *closegap;
          drawmod_path_closelinestr *closeline;
          drawmod_path_bezierstr    *bezier;
          drawmod_path_gaptostr     *gapto;
          drawmod_path_linetostr    *lineto;

          char  *bytep;
          int   *wordp;

        } drawmod_pathelemptr;

/****************************** fill type **********************************/

typedef enum
        {
          fill_Default        = 0x00000000,  /* default fill style - "fill to
                                              * halfway through boundary,
                                              * non-zero winding rule"
                                              * NOTE: if used this should not
                                              * be ORed with any other types
                                              */
          fill_WNonzero       = 0x00000000,  /* non-zero winding rule */
          fill_WNegative      = 0x00000001,  /* negative   "       "  */
          fill_WEvenodd       = 0x00000002,  /* even-odd   "       "  */
          fill_WPositive      = 0x00000003,  /* positve    "       "  */

          fill_FNonbext       = 0x00000004,  /* plot non-boundary exterior
                                              * pixels
                                              */
          fill_FBext          = 0x00000008,  /* plot boundary exterior
                                              * pixels
                                              */
          fill_FNonbint       = 0x00000010,  /* plot boundary interior
                                              * pixels
                                              */
          fill_FBint          = 0x00000020,  /* plot non-boundary interior
                                              * pixels
                                              */
                /**************************************
                 **************** NOTE ****************
                 * The following should only be used in
                 * drawmod_processpath.
                 **************************************
                 **************************************
                 */

          fill_PClose         = 0x08000000,  /* close open subpaths */
          fill_PFlatten       = 0x10000000,  /* flatten the path */
          fill_PThicken       = 0x20000000,  /* thicken the path */
          fill_PReflatten     = 0x40000000   /* re-flatten the path */

                                             /* NOTE: floating point not
                                              * supported so no 0x80000000.
                                              */

        } drawmod_filltype;

/************************** line cap and join specs ************************/

/* Permissible join style values */

#define join_mitred    ((unsigned char)0x00)  /* mitred joins */
#define join_round     ((unsigned char)0x01)  /* round joins */
#define join_bevelled  ((unsigned char)0x02)  /* bevelled joins */

/* Permissible cap style values */

#define cap_butt       ((unsigned char)0x00)  /* butt caps */
#define cap_round      ((unsigned char)0x01)  /* round caps */
#define cap_square     ((unsigned char)0x02)  /* projecting square caps */
#define cap_triang     ((unsigned char)0x03)  /* triangular caps */

typedef struct
        {
          unsigned char join;                /* join style */
          unsigned char leadcap;             /* leading cap style */
          unsigned char trailcap;            /* trailing cap style */
          unsigned char reserved8;           /* must be zero */
          int  mitrelimit;                   /* limit for mitred joins */

          unsigned short lead_tricap_w;     /* "width" of leading triangular
                                             * caps
                                             */
          unsigned short lead_tricap_h;     /* "height of leading triangular
                                             * caps
                                             */
          unsigned short trail_tricap_w;    /* "width" of trailing triangular
                                             * caps
                                             */
          unsigned short trail_tricap_h;    /* "height" of trailing
                                             * triangular caps
                                             */

        } drawmod_capjoinspec;

/***************************** dash patterns *******************************/
/*
 * NOTE: This is the "header" for a dash pattern. It should be followed
 * immediately in memory by the dash pattern itself. Each element of the
 * dash pattern is a distance.
 */

typedef struct
        {
          int dashstart;     /* distance into dash pattern to start */
          int dashcount;     /* number of elements in the dash pattern */
        } drawmod_dashhdr;

/***************************** Line attributes *****************************/
/*
 * A line can have the following attributes:
 *            Flatness:  given in user coords (0 means default == 2 OS units)
 *            Thickness: 0 means one pixel wide, with line caps/joins
 *                       ignored
 *            Cap and Join specification: deals with joins and leading/
 *                                        trailing caps.
 *                                        see #defines in the line and cap
 *                                        spec section above for their
 *                                        permissible values.
 *            Dash pattern:  A contiguous block of memory, consisting of
 *                           a header followed by a number of dash pattern
 *                           elements.
 *
 */


typedef struct
        {
          int flatness;
          int thickness;
          drawmod_capjoinspec spec;
          drawmod_dashhdr *dash_pattern;
        } drawmod_line;


/*************************** transformation matrix *************************/
/*
 * The transformation matrix has six elements (say a,b,c,d,e,f), where
 * elements appear in the standard matrix thus:
 *                ( a b 0 )
 *                ( c d 0 )
 *                ( e f 1 )
 * a,b,c,d should be considered as having 16 binary places (ie. 0x10000 is
 * given to represent 1.0); e and f represent a translation in output units
 *
 */

typedef  int drawmod_transmat[6];


/******************************* path buffer *******************************/
/*
 * This data type is used both as an input path buffer and an output path
 * buffer header. Typically, you should allocate enough space for your path
 * and then set a variable of type drawmod_buffer* to point at it.
 * NOTE that on passing to functions in this module which take a
 * drawmod_buffer* parameter, field zeroword should contain 0,and
 * sizeword should indicate how many bytes follow in memory.
 *
 */

typedef struct
        {
          int zeroword;
          int sizeword;
        } drawmod_buffer;


/**************************** options for process path *********************/

typedef  enum
         {
            tag_fill = 1,
            tag_box  = 2,
            tag_buf  = 3
         } drawmod_tagtype;

typedef  enum
         {  option_insitu      = 0,  /* output path to input path */
            option_normalfill  = 1,  /* fill normally */
            option_subpathfill = 2,  /* fill subpath by subpath */
            option_countsize   = 3   /* count size of required buffer */
         } drawmod_filling_options;

typedef  struct
         {
           int lowx;
           int lowY;
           int highX;
           int highY;
         } drawmod_box;

typedef  struct
         {
           drawmod_tagtype tag;
           union
           {
              drawmod_filling_options opts;
              drawmod_box *box;      /* pointer to word-aligned, four-word
                                      * area to hold bounding box of
                                      * processed path.
                                      */
              drawmod_buffer *buffer;
           } data;
         } drawmod_options;




/* ----------------------------- drawmod_fill ------------------------------
 * Description:   Emulate Postscript "fill" operator - ie. close open
 *                subpaths, flatten the path, transform it to standard coords
 *                and fill the result.
 *
 * Parameters:    drawmod_pathelemptr path_seq - sequence of path elements
 *                drawmod_filltype fill_style - style of fill
 *                drawmod_transmat *matrix - transformation matrix
 *                                           (0 for the identity matrix)
 *                int flatness - flatness in user coords (0 means default)
 *
 * Returns:       possible error condition
 * Other Info:    none.
 *
 */

os_error *drawmod_fill(drawmod_pathelemptr path_seq,
                       drawmod_filltype fill_style,
                       drawmod_transmat *matrix,
                       int flatness);


/* -------------------------- drawmod_stroke -------------------------------
 * Description:   Emulate PostScript "stroke" operator.
 *
 * Parameters:    drawmod_pathelemptr path_seq - sequence of path elements
 *                drawmod_filltype fill_style - style of fill
 *                drawmod_transmat *matrix - transformation matrix
 *                                           (0 means identity matrix)
 *                drawmod_line *line_style - (see typedef above for details)
 *
 * Returns:       possible error condition.
 * Other Info:    none.
 *
 */

os_error *drawmod_stroke(drawmod_pathelemptr path_seq,
                         drawmod_filltype fill_style,
                         drawmod_transmat *matrix,
                         drawmod_line *line_style);


/* -------------------------- drawmod_do_strokepath ------------------------
 * Description:   Puts path through all stages of drawmod_stroke except the
 *                final fill. Resulting path is placed in the buffer.
 *
 * Parameters:    drawmod_pathelemptr path_seq - sequence of path elements
 *                drawmod_transmat *matrix - transformation matrix
 *                drawmod_line *line_style - (see typedef above for details)
 *                drawmod_buffer *buffer - buffer to hold stroked path.
 * Returns:       possible error condition
 * Other Info:    none.
 *
 */

os_error *drawmod_do_strokepath(drawmod_pathelemptr path_seq,
                                drawmod_transmat *matrix,
                                drawmod_line *line_style,
                                drawmod_buffer *buffer);


/* ------------------------ drawmod_ask_strokepath -------------------------
 * Description:   Puts path through all stages of drawmod_stroke, except the
 *                fill, and returns the size of buffer needed to hold such
 *                a path.
 *
 * Parameters:    drawmod_pathelemptr path_seq - sequence of path elements
 *                drawmod_transmat *matrix - transformation matrix
 *                drawmod_line *line_style - (see typedef above for details)
 *                int *buflen - returned length of required buffer.
 * Returns:       possible error condition.
 * Other Info:    none.
 *
 */

os_error *drawmod_ask_strokepath(drawmod_pathelemptr path_seq,
                                 drawmod_transmat *matrix,
                                 drawmod_line *line_style,
                                 int *buflen);


/* -------------------------- drawmod_do_flattenpath -----------------------
 * Description:   Flatten the given path, and put into the supplied buffer.
 *
 * Parameters:    drawmod_pathelemptr path_seq - sequence of path elements
 *                drwamod_buffer *buffer - buffer to hold flattened path
 *                int flatness - required flatness.
 *
 * Returns:       possible error condition.
 * Other Info:    none.
 *
 */

os_error *drawmod_do_flattenpath(drawmod_pathelemptr path_seq,
                                 drawmod_buffer *buffer,
                                 int flatness);


/* -------------------------- drawmod_ask_flattenpath ----------------------
 * Description:   Put the given path through the stages of
 *                drawmod_flattenpath and return the size of buffer needed
 *                to hold the resulting path.
 *
 * Parameters:    drawmod_pathelemptr path_seq - sequence of path elements
 *                int flatness - required flatness.
 *                int *buflen - returned length of required buffer.
 * Returns:       possible error condition.
 * Other Info:    none.
 *
 */

os_error *drawmod_ask_flattenpath(drawmod_pathelemptr path_seq,
                                  int flatness,
                                  int *buflen);


/* -------------------------- drawmod_buf_transformpath --------------------
 * Description:   Put a path through a transformation matrix, and put the
 *                result in the supplied buffer.
 *
 * Parameters:    drawmod_pathelemptr path_seq - sequenec of path elements
 *                drawmod_buffer *buffer - buffer to hold transformed path
 *                drawmod_transmat *matrix - the transformation matrix.
 * Returns:       possible error condition.
 * Other Info:    none.
 *
 */

os_error *drawmod_buf_transformpath(drawmod_pathelemptr path_seq,
                                    drawmod_buffer *buffer,
                                    drawmod_transmat *matrix);


/* ----------------------- drawmod_insitu_transformpath --------------------
 * Description:   Put a path through a transformation matrix, by modifying
 *                the supplied path itself.
 *
 * Parameters:    drawmod_pathelemptr path_seq - sequence of path elements
 *                drawmod_transmat *matrix - the transformation matrix.
 * Returns:       possible error condition.
 * Other Info:    none.
 *
 */

os_error *drawmod_insitu_transformpath(drawmod_pathelemptr path_seq,
                                       drawmod_transmat *matrix);


/* -------------------------- drawmod_processpath --------------------------
 * Description:   Put the path through a set of processes used when doing
 *                Stroke and Fill.
 *
 * Parameters:    drawmod_pathelemptr path_seq - sequence of path elements
 *                drawmod_filltype fill_style - style of fill
 *                drawmod_transmat *matrix - the transformation matrix
 *                drawmod_line *line_style - (see typedef above for details)
 *                drawmod_options *options - this can have the values
 *                                           detailed below. Note: pass in
 *                                           address of a draw_options struct
 *                int *buflen - returned length of required buffer
 *                              (only used when options->tagtype==tag_fill
 *                               && options->data.opts == option_countsize).  * Returns:       possible error condition.
 * Other Info:    Possible values for options:
 *                     drawmod_insitu: output to the input path
 *                                     (only if path size wouldn't change)
 *                     drawmod_fillnormal : fill path normally
 *                     drawmod_fillsubpath : fill path, subpath by subpath
 *                  OR an address : output bounding box of path to the
 *                                  word-aligned address, and three next
 *                                  words, with word-order lowX, lowY,
 *                                  highX, highY
 *                  OR a buffer to hold processed path.
 *
 */

os_error *drawmod_processpath(drawmod_pathelemptr path_seq,
                              drawmod_filltype fill_style,
                              drawmod_transmat *matrix,
                              drawmod_line *line_style,
                              drawmod_options *options,
                              int *buflen);

#endif

/* end drawmod.h */