Revise the printing colour framework so that we can explicitly

request either of hatching or halftoning, and also choose which to
supply as a fallback when printing in colour.

[originally from svn r7976]
This commit is contained in:
Simon Tatham
2008-04-07 17:13:29 +00:00
parent 30da25262d
commit 0564211167
9 changed files with 172 additions and 105 deletions

View File

@ -1991,7 +1991,7 @@ black; if \c{grey} is 1, the colour is white.
\S{print-grey-colour} \cw{print_grey_colour()} \S{print-grey-colour} \cw{print_grey_colour()}
\c int print_grey_colour(drawing *dr, int hatch, float grey); \c int print_grey_colour(drawing *dr, float grey);
This function allocates a colour index for a grey-scale colour This function allocates a colour index for a grey-scale colour
during printing. during printing.
@ -1999,18 +1999,17 @@ during printing.
\c{grey} may be any number between 0 (black) and 1 (white); for \c{grey} may be any number between 0 (black) and 1 (white); for
example, 0.5 indicates a medium grey. example, 0.5 indicates a medium grey.
If printing in black and white only, the \c{grey} value will not be The chosen colour will be rendered to the limits of the printer's
used; instead, regions shaded in this colour will be hatched with halftoning capability.
parallel lines. The \c{hatch} parameter defines what type of
hatching should be used in place of this colour:
\dt \cw{HATCH_SOLID} \S{print-hatched-colour} \cw{print_hatched_colour()}
\dd In black and white, this colour will be replaced by solid black. \c int print_hatched_colour(drawing *dr, int hatch);
\dt \cw{HATCH_CLEAR} This function allocates a colour index which does not represent a
literal \e{colour}. Instead, regions shaded in this colour will be
\dd In black and white, this colour will be replaced by solid white. hatched with parallel lines. The \c{hatch} parameter defines what
type of hatching should be used in place of this colour:
\dt \cw{HATCH_SLASH} \dt \cw{HATCH_SLASH}
@ -2039,29 +2038,59 @@ vertical lines.
\dd This colour will be hatched by criss-crossing diagonal lines. \dd This colour will be hatched by criss-crossing diagonal lines.
Colours defined to use hatching may not be used for drawing lines; Colours defined to use hatching may not be used for drawing lines or
they may only be used for filling areas. That is, they may be used text; they may only be used for filling areas. That is, they may be
as the \c{fillcolour} parameter to \cw{draw_circle()} and used as the \c{fillcolour} parameter to \cw{draw_circle()} and
\cw{draw_polygon()}, and as the colour parameter to \cw{draw_polygon()}, and as the colour parameter to
\cw{draw_rect()}, but may not be used as the \c{outlinecolour} \cw{draw_rect()}, but may not be used as the \c{outlinecolour}
parameter to \cw{draw_circle()} or \cw{draw_polygon()}, or with parameter to \cw{draw_circle()} or \cw{draw_polygon()}, or with
\cw{draw_line()}. \cw{draw_line()} or \cw{draw_text()}.
\S{print-rgb-colour} \cw{print_rgb_colour()} \S{print-rgb-mono-colour} \cw{print_rgb_mono_colour()}
\c int print_rgb_colour(drawing *dr, int hatch, \c int print_rgb_mono_colour(drawing *dr, float r, float g,
\c float r, float g, float b); \c float b, float grey);
This function allocates a colour index for a fully specified RGB This function allocates a colour index for a fully specified RGB
colour during printing. colour during printing.
\c{r}, \c{g} and \c{b} may each be anywhere in the range from 0 to 1. \c{r}, \c{g} and \c{b} may each be anywhere in the range from 0 to 1.
If printing in black and white only, these values will not be used; If printing in black and white only, these values will be ignored,
instead, regions shaded in this colour will be hatched with parallel and either pure black or pure white will be used instead, according
lines. The \c{hatch} parameter defines what type of hatching should to the \q{grey} parameter. (The fallback colour is the same as the
be used in place of this colour; see \k{print-grey-colour} for its one which would be allocated by \cw{print_mono_colour(grey)}.)
definition.
\S{print-rgb-grey-colour} \cw{print_rgb_grey_colour()}
\c int print_rgb_grey_colour(drawing *dr, float r, float g,
\c float b, float grey);
This function allocates a colour index for a fully specified RGB
colour during printing.
\c{r}, \c{g} and \c{b} may each be anywhere in the range from 0 to 1.
If printing in black and white only, these values will be ignored,
and a shade of grey given by the \c{grey} parameter will be used
instead. (The fallback colour is the same as the one which would be
allocated by \cw{print_grey_colour(grey)}.)
\S{print-rgb-hatched-colour} \cw{print_rgb_hatched_colour()}
\c int print_rgb_hatched_colour(drawing *dr, float r, float g,
\c float b, float hatched);
This function allocates a colour index for a fully specified RGB
colour during printing.
\c{r}, \c{g} and \c{b} may each be anywhere in the range from 0 to 1.
If printing in black and white only, these values will be ignored,
and a form of cross-hatching given by the \c{hatch} parameter will
be used instead; see \k{print-hatched-colour} for the possible
values of this parameter. (The fallback colour is the same as the
one which would be allocated by \cw{print_hatched_colour(hatch)}.)
\S{print-line-width} \cw{print_line_width()} \S{print-line-width} \cw{print_line_width()}
@ -2395,20 +2424,27 @@ the front end.
\S{drawing-print-get-colour} \cw{print_get_colour()} \S{drawing-print-get-colour} \cw{print_get_colour()}
\c void print_get_colour(drawing *dr, int colour, int *hatch, \c void print_get_colour(drawing *dr, int colour, int printincolour,
\c float *r, float *g, float *b) \c int *hatch, float *r, float *g, float *b)
This function is called by the implementations of the drawing API This function is called by the implementations of the drawing API
functions when they are called in a printing context. It takes a functions when they are called in a printing context. It takes a
colour index as input, and returns the description of the colour as colour index as input, and returns the description of the colour as
requested by the back end. requested by the back end.
\c{*r}, \c{*g} and \c{*b} are filled with the RGB values of the \c{printincolour} is \cw{TRUE} iff the implementation is printing in
desired colour if printing in colour. colour. This will alter the results returned if the colour in
question was specified with a black-and-white fallback value.
\c{*hatch} is filled with the type of hatching (or not) desired if If the colour should be rendered by hatching, \c{*hatch} is filled
printing in black and white. See \k{print-grey-colour} for details with the type of hatching desired. See \k{print-grey-colour} for
of the values this integer can take. details of the values this integer can take.
If the colour should be rendered as solid colour, \c{*hatch} is
given a negative value, and \c{*r}, \c{*g} and \c{*b} are filled
with the RGB values of the desired colour (if printing in colour),
or all filled with the grey-scale value (if printing in black and
white).
\C{midend} The API provided by the mid-end \C{midend} The API provided by the mid-end

View File

@ -33,7 +33,9 @@
struct print_colour { struct print_colour {
int hatch; int hatch;
int hatch_when; /* 0=never 1=only-in-b&w 2=always */
float r, g, b; float r, g, b;
float grey;
}; };
struct drawing { struct drawing {
@ -199,17 +201,27 @@ void print_end_doc(drawing *dr)
dr->api->end_doc(dr->handle); dr->api->end_doc(dr->handle);
} }
void print_get_colour(drawing *dr, int colour, int *hatch, void print_get_colour(drawing *dr, int colour, int printing_in_colour,
float *r, float *g, float *b) int *hatch, float *r, float *g, float *b)
{ {
assert(colour >= 0 && colour < dr->ncolours); assert(colour >= 0 && colour < dr->ncolours);
*hatch = dr->colours[colour].hatch; if (dr->colours[colour].hatch_when == 2 ||
*r = dr->colours[colour].r; (dr->colours[colour].hatch_when == 1 && !printing_in_colour)) {
*g = dr->colours[colour].g; *hatch = dr->colours[colour].hatch;
*b = dr->colours[colour].b; } else {
*hatch = -1;
if (printing_in_colour) {
*r = dr->colours[colour].r;
*g = dr->colours[colour].g;
*b = dr->colours[colour].b;
} else {
*r = *g = *b = dr->colours[colour].grey;
}
}
} }
int print_rgb_colour(drawing *dr, int hatch, float r, float g, float b) static int print_generic_colour(drawing *dr, float r, float g, float b,
float grey, int hatch, int hatch_when)
{ {
if (dr->ncolours >= dr->coloursize) { if (dr->ncolours >= dr->coloursize) {
dr->coloursize = dr->ncolours + 16; dr->coloursize = dr->ncolours + 16;
@ -217,21 +229,42 @@ int print_rgb_colour(drawing *dr, int hatch, float r, float g, float b)
struct print_colour); struct print_colour);
} }
dr->colours[dr->ncolours].hatch = hatch; dr->colours[dr->ncolours].hatch = hatch;
dr->colours[dr->ncolours].hatch_when = hatch_when;
dr->colours[dr->ncolours].r = r; dr->colours[dr->ncolours].r = r;
dr->colours[dr->ncolours].g = g; dr->colours[dr->ncolours].g = g;
dr->colours[dr->ncolours].b = b; dr->colours[dr->ncolours].b = b;
dr->colours[dr->ncolours].grey = grey;
return dr->ncolours++; return dr->ncolours++;
} }
int print_grey_colour(drawing *dr, int hatch, float grey)
{
return print_rgb_colour(dr, hatch, grey, grey, grey);
}
int print_mono_colour(drawing *dr, int grey) int print_mono_colour(drawing *dr, int grey)
{ {
return print_rgb_colour(dr, grey ? HATCH_CLEAR : HATCH_SOLID, return print_generic_colour(dr, grey, grey, grey, grey, -1, 0);
grey, grey, grey); }
int print_grey_colour(drawing *dr, float grey)
{
return print_generic_colour(dr, grey, grey, grey, grey, -1, 0);
}
int print_hatched_colour(drawing *dr, int hatch)
{
return print_generic_colour(dr, 0, 0, 0, 0, hatch, 2);
}
int print_rgb_mono_colour(drawing *dr, float r, float g, float b, int grey)
{
return print_generic_colour(dr, r, g, b, grey, -1, 0);
}
int print_rgb_grey_colour(drawing *dr, float r, float g, float b, float grey)
{
return print_generic_colour(dr, r, g, b, grey, -1, 0);
}
int print_rgb_hatched_colour(drawing *dr, float r, float g, float b, int hatch)
{
return print_generic_colour(dr, r, g, b, 0, hatch, 1);
} }
void print_line_width(drawing *dr, int width) void print_line_width(drawing *dr, int width)

View File

@ -3252,9 +3252,9 @@ static void game_print(drawing *dr, game_state *state, int sz)
game_drawstate ads, *ds = &ads; game_drawstate ads, *ds = &ads;
ds->tilesize = sz; ds->tilesize = sz;
white = print_grey_colour(dr, HATCH_CLEAR, 1.0F); white = print_mono_colour(dr, 1);
black = print_grey_colour(dr, HATCH_SOLID, 0.0F); black = print_mono_colour(dr, 0);
blackish = print_grey_colour(dr, HATCH_X, 0.5F); blackish = print_hatched_colour(dr, HATCH_X);
/* /*
* Get the completion information. * Get the completion information.

5
map.c
View File

@ -2977,8 +2977,9 @@ static void game_print(drawing *dr, game_state *state, int tilesize)
ink = print_mono_colour(dr, 0); ink = print_mono_colour(dr, 0);
for (i = 0; i < FOUR; i++) for (i = 0; i < FOUR; i++)
c[i] = print_rgb_colour(dr, map_hatching[i], map_colours[i][0], c[i] = print_rgb_hatched_colour(dr, map_colours[i][0],
map_colours[i][1], map_colours[i][2]); map_colours[i][1], map_colours[i][2],
map_hatching[i]);
coordsize = 0; coordsize = 0;
coords = NULL; coords = NULL;

View File

@ -27,8 +27,13 @@ void blitter_free(drawing *dr, blitter *bl) {}
void blitter_save(drawing *dr, blitter *bl, int x, int y) {} void blitter_save(drawing *dr, blitter *bl, int x, int y) {}
void blitter_load(drawing *dr, blitter *bl, int x, int y) {} void blitter_load(drawing *dr, blitter *bl, int x, int y) {}
int print_mono_colour(drawing *dr, int grey) { return 0; } int print_mono_colour(drawing *dr, int grey) { return 0; }
int print_grey_colour(drawing *dr, int hatch, float grey) { return 0; } int print_grey_colour(drawing *dr, float grey) { return 0; }
int print_rgb_colour(drawing *dr, int hatch, float r, float g, float b) int print_hatched_colour(drawing *dr, int hatch) { return 0; }
int print_rgb_mono_colour(drawing *dr, float r, float g, float b, int grey)
{ return 0; }
int print_rgb_grey_colour(drawing *dr, float r, float g, float b, float grey)
{ return 0; }
int print_rgb_hatched_colour(drawing *dr, float r, float g, float b, int hatch)
{ return 0; } { return 0; }
void print_line_width(drawing *dr, int width) {} void print_line_width(drawing *dr, int width) {}
void midend_supersede_game_desc(midend *me, char *desc, char *privdesc) {} void midend_supersede_game_desc(midend *me, char *desc, char *privdesc) {}

34
ps.c
View File

@ -35,12 +35,13 @@ static void ps_fill(psdata *ps, int colour)
int hatch; int hatch;
float r, g, b; float r, g, b;
print_get_colour(ps->drawing, colour, &hatch, &r, &g, &b); print_get_colour(ps->drawing, colour, ps->colour, &hatch, &r, &g, &b);
if (ps->colour) { if (hatch < 0) {
ps_printf(ps, "%g %g %g setrgbcolor fill\n", r, g, b); if (ps->colour)
} else if (hatch == HATCH_SOLID || hatch == HATCH_CLEAR) { ps_printf(ps, "%g %g %g setrgbcolor fill\n", r, g, b);
ps_printf(ps, "%d setgray fill\n", hatch == HATCH_CLEAR); else
ps_printf(ps, "%g setgray fill\n", r);
} else { } else {
/* Clip to the region. */ /* Clip to the region. */
ps_printf(ps, "gsave clip\n"); ps_printf(ps, "gsave clip\n");
@ -77,20 +78,17 @@ static void ps_setcolour_internal(psdata *ps, int colour, char *suffix)
int hatch; int hatch;
float r, g, b; float r, g, b;
print_get_colour(ps->drawing, colour, &hatch, &r, &g, &b); print_get_colour(ps->drawing, colour, ps->colour, &hatch, &r, &g, &b);
if (ps->colour) { /*
if (r != g || r != b) * Stroking in hatched colours is not permitted.
ps_printf(ps, "%g %g %g setrgbcolor%s\n", r, g, b, suffix); */
else assert(hatch < 0);
ps_printf(ps, "%g setgray%s\n", r, suffix);
} else { if (ps->colour)
/* ps_printf(ps, "%g %g %g setrgbcolor%s\n", r, g, b, suffix);
* Stroking in hatched colours is not permitted. else
*/ ps_printf(ps, "%g setgray%s\n", r, suffix);
assert(hatch == HATCH_SOLID || hatch == HATCH_CLEAR);
ps_printf(ps, "%d setgray%s\n", hatch == HATCH_CLEAR, suffix);
}
} }
static void ps_setcolour(psdata *ps, int colour) static void ps_setcolour(psdata *ps, int colour)

View File

@ -110,14 +110,12 @@ typedef struct psdata psdata;
#define FONT_VARIABLE 1 #define FONT_VARIABLE 1
/* For printing colours */ /* For printing colours */
#define HATCH_SOLID 0 #define HATCH_SLASH 1
#define HATCH_CLEAR 1 #define HATCH_BACKSLASH 2
#define HATCH_SLASH 2 #define HATCH_HORIZ 3
#define HATCH_BACKSLASH 3 #define HATCH_VERT 4
#define HATCH_HORIZ 4 #define HATCH_PLUS 5
#define HATCH_VERT 5 #define HATCH_X 6
#define HATCH_PLUS 6
#define HATCH_X 7
/* /*
* Structure used to pass configuration data between frontend and * Structure used to pass configuration data between frontend and
@ -205,11 +203,15 @@ void print_begin_puzzle(drawing *dr, float xm, float xc,
void print_end_puzzle(drawing *dr); void print_end_puzzle(drawing *dr);
void print_end_page(drawing *dr, int number); void print_end_page(drawing *dr, int number);
void print_end_doc(drawing *dr); void print_end_doc(drawing *dr);
void print_get_colour(drawing *dr, int colour, int *hatch, void print_get_colour(drawing *dr, int colour, int printing_in_colour,
float *r, float *g, float *b); int *hatch, float *r, float *g, float *b);
int print_mono_colour(drawing *dr, int grey); /* 0==black, 1==white */ int print_mono_colour(drawing *dr, int grey); /* 0==black, 1==white */
int print_grey_colour(drawing *dr, int hatch, float grey); int print_grey_colour(drawing *dr, float grey);
int print_rgb_colour(drawing *dr, int hatch, float r, float g, float b); int print_hatched_colour(drawing *dr, int hatch);
int print_rgb_mono_colour(drawing *dr, float r, float g, float b, float mono);
int print_rgb_grey_colour(drawing *dr, float r, float g, float b, float grey);
int print_rgb_hatched_colour(drawing *dr, float r, float g, float b,
int hatch);
void print_line_width(drawing *dr, int width); void print_line_width(drawing *dr, int width);
/* /*

2
solo.c
View File

@ -3719,7 +3719,7 @@ static void game_print(drawing *dr, game_state *state, int tilesize)
*/ */
if (state->xtype) { if (state->xtype) {
int i; int i;
int xhighlight = print_grey_colour(dr, HATCH_SLASH, 0.90F); int xhighlight = print_grey_colour(dr, 0.90F);
for (i = 0; i < cr; i++) for (i = 0; i < cr; i++)
draw_rect(dr, BORDER + i*TILE_SIZE, BORDER + i*TILE_SIZE, draw_rect(dr, BORDER + i*TILE_SIZE, BORDER + i*TILE_SIZE,

View File

@ -398,12 +398,14 @@ static void win_text_colour(frontend *fe, int colour)
if (fe->drawstatus == PRINTING) { if (fe->drawstatus == PRINTING) {
int hatch; int hatch;
float r, g, b; float r, g, b;
print_get_colour(fe->dr, colour, &hatch, &r, &g, &b); print_get_colour(fe->dr, colour, fe->printcolour, &hatch, &r, &g, &b);
if (fe->printcolour)
SetTextColor(fe->hdc, RGB(r * 255, g * 255, b * 255)); /*
else * Displaying text in hatched colours is not permitted.
SetTextColor(fe->hdc, */
hatch == HATCH_CLEAR ? RGB(255,255,255) : RGB(0,0,0)); assert(hatch < 0);
SetTextColor(fe->hdc, RGB(r * 255, g * 255, b * 255));
} else { } else {
SetTextColor(fe->hdc, fe->colours[colour]); SetTextColor(fe->hdc, fe->colours[colour]);
} }
@ -417,14 +419,10 @@ static void win_set_brush(frontend *fe, int colour)
if (fe->drawstatus == PRINTING) { if (fe->drawstatus == PRINTING) {
int hatch; int hatch;
float r, g, b; float r, g, b;
print_get_colour(fe->dr, colour, &hatch, &r, &g, &b); print_get_colour(fe->dr, colour, fe->printcolour, &hatch, &r, &g, &b);
if (fe->printcolour) { if (hatch < 0) {
br = CreateSolidBrush(RGB(r * 255, g * 255, b * 255)); br = CreateSolidBrush(RGB(r * 255, g * 255, b * 255));
} else if (hatch == HATCH_SOLID) {
br = CreateSolidBrush(RGB(0,0,0));
} else if (hatch == HATCH_CLEAR) {
br = CreateSolidBrush(RGB(255,255,255));
} else { } else {
#ifdef _WIN32_WCE #ifdef _WIN32_WCE
/* /*
@ -469,18 +467,12 @@ static void win_set_pen(frontend *fe, int colour, int thin)
float r, g, b; float r, g, b;
int width = thin ? 0 : fe->linewidth; int width = thin ? 0 : fe->linewidth;
print_get_colour(fe->dr, colour, &hatch, &r, &g, &b); print_get_colour(fe->dr, colour, fe->printcolour, &hatch, &r, &g, &b);
if (fe->printcolour) /*
pen = CreatePen(PS_SOLID, width, * Stroking in hatched colours is not permitted.
RGB(r * 255, g * 255, b * 255)); */
else if (hatch == HATCH_SOLID) assert(hatch < 0);
pen = CreatePen(PS_SOLID, width, RGB(0, 0, 0)); pen = CreatePen(PS_SOLID, width, RGB(r * 255, g * 255, b * 255));
else if (hatch == HATCH_CLEAR)
pen = CreatePen(PS_SOLID, width, RGB(255,255,255));
else {
assert(!"This shouldn't happen");
pen = CreatePen(PS_SOLID, 1, RGB(0, 0, 0));
}
} else { } else {
pen = fe->pens[colour]; pen = fe->pens[colour];
} }