mirror of
git://git.tartarus.org/simon/puzzles.git
synced 2025-04-20 07:31:30 -07:00
Refine drawing API semantics to pass drawing *
instead of void *
This changes the drawing API so that implementations receive a `drawing *` pointer with each call, instead of a `void *` pointer as they did previously. The `void *` context pointer has been moved to be a member of the `drawing` structure (which has been made public), from which it can be retrieved via the new `GET_HANDLE_AS_TYPE()` macro. To signal this breaking change to downstream front end authors, I've added a version number to the `drawing_api` struct, which will hopefully force them to notice. The motivation for this change is the upcoming introduction of a draw_polygon_fallback() function, which will use a series of calls to draw_line() to perform software polygon rasterization on platforms without a native polygon fill primitive. This function is fairly large, so I desired that it not be included in the binary distribution, except on platforms which require it (e.g. my Rockbox port). One way to achieve this is via link-time optimization (LTO, a.k.a. "interprocedural optimization"/IPO), so that the code is unconditionally compiled (preventing bit-rot) but only included in the linked executable if it is actually referenced from elsewhere. Practically, this precludes the otherwise straightforward route of including a run-time check of the `draw_polygon` pointer in the drawing.c middleware. Instead, Simon recommended that a front end be able to set its `draw_polygon` field to point to draw_polygon_fallback(). However, the old drawing API's semantics of passing a `void *` pointer prevented this from working in practice, since draw_polygon_fallback(), implemented in middleware, would not be able to perform any drawing operations without a `drawing *` pointer; with the new API, this restriction is removed, clearing the way for that function's introduction. This is a breaking change for front ends, which must update their implementations of the drawing API to conform. The migration process is fairly straightforward: every drawing API function which previously took a `void *` context pointer should be updated to take a `drawing *` pointer in its place. Then, where each such function would have previously casted the `void *` pointer to a meaningful type, they now instead retrieve the context pointer from the `handle` field of the `drawing` structure. To make this transition easier, the `GET_HANDLE_AS_TYPE()` macro is introduced to wrap the context pointer retrieval (see below for usage). As an example, an old drawing API function implementation would have looked like this: void frontend_draw_func(void *handle, ...) { frontend *fe = (frontend *)handle; /* do stuff with fe */ } After this change, that function would be rewritten as: void frontend_draw_func(drawing *dr, ...) { frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend); /* do stuff with fe */ } I have already made these changes to all the in-tree front ends, but out-of-tree front ends will need to follow the procedure outlined above. Simon pointed out that changing the drawing API function pointer signatures to take `drawing *` instead of `void *` results only in a compiler warning, not an outright error. Thus, I've introduced a version field to the beginning of the `drawing_api` struct, which will cause a compilation error and hopefully force front ends to notice this. This field should be set to 1 for now. Going forward, it will provide a clear means of communicating future breaking API changes.
This commit is contained in:

committed by
Simon Tatham

parent
a993fd45eb
commit
f37913002a
128
devel.but
128
devel.but
@ -1975,18 +1975,19 @@ In fact these global functions are not implemented directly by the
|
|||||||
front end; instead, they are implemented centrally in \c{drawing.c}
|
front end; instead, they are implemented centrally in \c{drawing.c}
|
||||||
and form a small piece of middleware. The drawing API as supplied by
|
and form a small piece of middleware. The drawing API as supplied by
|
||||||
the front end is a structure containing a set of function pointers,
|
the front end is a structure containing a set of function pointers,
|
||||||
plus a \cq{void *} handle which is passed to each of those
|
plus a \cq{void *} handle which is indirectly passed to each of those
|
||||||
functions. This enables a single front end to switch between
|
functions as a member of the same drawing object as used by the
|
||||||
multiple implementations of the drawing API if necessary. For
|
backend. This enables a single front end to switch between multiple
|
||||||
example, the Windows API supplies a printing mechanism integrated
|
implementations of the drawing API if necessary. For example, the
|
||||||
into the same GDI which deals with drawing in windows, and therefore
|
Windows API supplies a printing mechanism integrated into the same GDI
|
||||||
the same API implementation can handle both drawing and printing;
|
which deals with drawing in windows, and therefore the same API
|
||||||
but on Unix, the most common way for applications to print is by
|
implementation can handle both drawing and printing; but on Unix, the
|
||||||
producing PostScript output directly, and although it would be
|
most common way for applications to print is by producing PostScript
|
||||||
\e{possible} to write a single (say) \cw{draw_rect()} function which
|
output directly, and although it would be \e{possible} to write a
|
||||||
checked a global flag to decide whether to do GTK drawing operations
|
single (say) \cw{draw_rect()} function which checked a global flag to
|
||||||
or output PostScript to a file, it's much nicer to have two separate
|
decide whether to do GTK drawing operations or output PostScript to a
|
||||||
functions and switch between them as appropriate.
|
file, it's much nicer to have two separate functions and switch
|
||||||
|
between them as appropriate.
|
||||||
|
|
||||||
When drawing, the puzzle window is indexed by pixel coordinates,
|
When drawing, the puzzle window is indexed by pixel coordinates,
|
||||||
with the top left pixel defined as \cw{(0,0)} and the bottom right
|
with the top left pixel defined as \cw{(0,0)} and the bottom right
|
||||||
@ -2689,17 +2690,38 @@ API; the platform-independent module \c{ps.c} also provides an
|
|||||||
implementation of it which outputs PostScript. Thus, any platform
|
implementation of it which outputs PostScript. Thus, any platform
|
||||||
which wants to do PS printing can do so with minimum fuss.)
|
which wants to do PS printing can do so with minimum fuss.)
|
||||||
|
|
||||||
The following entries all describe function pointer fields in a
|
The following entries (with the exception of the \cw{version} field)
|
||||||
structure called \c{drawing_api}. Each of the functions takes a
|
all describe function pointer fields in a structure called
|
||||||
\cq{void *} context pointer, which it should internally cast back to
|
\c{drawing_api}. Each of the functions takes a \cq{drawing *} pointer,
|
||||||
a more useful type. Thus, a drawing \e{object} (\c{drawing *)}
|
which in turn contains a \cq{void *handle} member that the front end
|
||||||
suitable for passing to the back end redraw or printing functions
|
can access and internally cast back to a more useful type. Since this
|
||||||
is constructed by passing a \c{drawing_api} and a \cq{void *} to the
|
is a fairly common thing for front ends to do, the
|
||||||
function \cw{drawing_new()} (see \k{drawing-new}).
|
\cw{GET_HANDLE_AS_TYPE()} macro is provided to do this for you (see
|
||||||
|
\k{utils-get-handle-as-type}).
|
||||||
|
|
||||||
|
A drawing \e{object} (\c{drawing *)} suitable for passing to the back
|
||||||
|
end redraw or printing functions is constructed by passing a
|
||||||
|
\c{drawing_api} and a \cq{void *} to the function \cw{drawing_new()}
|
||||||
|
(see \k{drawing-new}).
|
||||||
|
|
||||||
|
\S{drawingapi-version} \cw{version}
|
||||||
|
|
||||||
|
\c int version;
|
||||||
|
|
||||||
|
This is an integer giving the version of the drawing API implemented
|
||||||
|
by the front end. For the version of the API described in this
|
||||||
|
document, this field should be \cw{1}.
|
||||||
|
|
||||||
|
On occasion, there may be a breaking change to the drawing API, such
|
||||||
|
as the introduction of a new function or a change to the semantics of
|
||||||
|
an existing function. The intent of this version field is to signal to
|
||||||
|
front end authors when such a breaking change occurs. As such changes
|
||||||
|
can be disruptive to downstream front ends, they should be done
|
||||||
|
sparingly.
|
||||||
|
|
||||||
\S{drawingapi-draw-text} \cw{draw_text()}
|
\S{drawingapi-draw-text} \cw{draw_text()}
|
||||||
|
|
||||||
\c void (*draw_text)(void *handle, int x, int y, int fonttype,
|
\c void (*draw_text)(drawing *dr, int x, int y, int fonttype,
|
||||||
\c int fontsize, int align, int colour,
|
\c int fontsize, int align, int colour,
|
||||||
\c const char *text);
|
\c const char *text);
|
||||||
|
|
||||||
@ -2708,7 +2730,7 @@ function; see \k{drawing-draw-text}.
|
|||||||
|
|
||||||
\S{drawingapi-draw-rect} \cw{draw_rect()}
|
\S{drawingapi-draw-rect} \cw{draw_rect()}
|
||||||
|
|
||||||
\c void (*draw_rect)(void *handle, int x, int y, int w, int h,
|
\c void (*draw_rect)(drawing *dr, int x, int y, int w, int h,
|
||||||
\c int colour);
|
\c int colour);
|
||||||
|
|
||||||
This function behaves exactly like the back end \cw{draw_rect()}
|
This function behaves exactly like the back end \cw{draw_rect()}
|
||||||
@ -2716,7 +2738,7 @@ function; see \k{drawing-draw-rect}.
|
|||||||
|
|
||||||
\S{drawingapi-draw-line} \cw{draw_line()}
|
\S{drawingapi-draw-line} \cw{draw_line()}
|
||||||
|
|
||||||
\c void (*draw_line)(void *handle, int x1, int y1, int x2, int y2,
|
\c void (*draw_line)(drawing *dr, int x1, int y1, int x2, int y2,
|
||||||
\c int colour);
|
\c int colour);
|
||||||
|
|
||||||
This function behaves exactly like the back end \cw{draw_line()}
|
This function behaves exactly like the back end \cw{draw_line()}
|
||||||
@ -2724,7 +2746,7 @@ function; see \k{drawing-draw-line}.
|
|||||||
|
|
||||||
\S{drawingapi-draw-polygon} \cw{draw_polygon()}
|
\S{drawingapi-draw-polygon} \cw{draw_polygon()}
|
||||||
|
|
||||||
\c void (*draw_polygon)(void *handle, const int *coords, int npoints,
|
\c void (*draw_polygon)(drawing *dr, const int *coords, int npoints,
|
||||||
\c int fillcolour, int outlinecolour);
|
\c int fillcolour, int outlinecolour);
|
||||||
|
|
||||||
This function behaves exactly like the back end \cw{draw_polygon()}
|
This function behaves exactly like the back end \cw{draw_polygon()}
|
||||||
@ -2732,7 +2754,7 @@ function; see \k{drawing-draw-polygon}.
|
|||||||
|
|
||||||
\S{drawingapi-draw-circle} \cw{draw_circle()}
|
\S{drawingapi-draw-circle} \cw{draw_circle()}
|
||||||
|
|
||||||
\c void (*draw_circle)(void *handle, int cx, int cy, int radius,
|
\c void (*draw_circle)(drawing *dr, int cx, int cy, int radius,
|
||||||
\c int fillcolour, int outlinecolour);
|
\c int fillcolour, int outlinecolour);
|
||||||
|
|
||||||
This function behaves exactly like the back end \cw{draw_circle()}
|
This function behaves exactly like the back end \cw{draw_circle()}
|
||||||
@ -2754,7 +2776,7 @@ and provide a low-quality alternative using \cw{draw_polygon()}.
|
|||||||
|
|
||||||
\S{drawingapi-draw-update} \cw{draw_update()}
|
\S{drawingapi-draw-update} \cw{draw_update()}
|
||||||
|
|
||||||
\c void (*draw_update)(void *handle, int x, int y, int w, int h);
|
\c void (*draw_update)(drawing *dr, int x, int y, int w, int h);
|
||||||
|
|
||||||
This function behaves exactly like the back end \cw{draw_update()}
|
This function behaves exactly like the back end \cw{draw_update()}
|
||||||
function; see \k{drawing-draw-update}.
|
function; see \k{drawing-draw-update}.
|
||||||
@ -2766,21 +2788,21 @@ than bothering to define an empty function. The middleware in
|
|||||||
|
|
||||||
\S{drawingapi-clip} \cw{clip()}
|
\S{drawingapi-clip} \cw{clip()}
|
||||||
|
|
||||||
\c void (*clip)(void *handle, int x, int y, int w, int h);
|
\c void (*clip)(drawing *dr, int x, int y, int w, int h);
|
||||||
|
|
||||||
This function behaves exactly like the back end \cw{clip()}
|
This function behaves exactly like the back end \cw{clip()}
|
||||||
function; see \k{drawing-clip}.
|
function; see \k{drawing-clip}.
|
||||||
|
|
||||||
\S{drawingapi-unclip} \cw{unclip()}
|
\S{drawingapi-unclip} \cw{unclip()}
|
||||||
|
|
||||||
\c void (*unclip)(void *handle);
|
\c void (*unclip)(drawing *dr);
|
||||||
|
|
||||||
This function behaves exactly like the back end \cw{unclip()}
|
This function behaves exactly like the back end \cw{unclip()}
|
||||||
function; see \k{drawing-unclip}.
|
function; see \k{drawing-unclip}.
|
||||||
|
|
||||||
\S{drawingapi-start-draw} \cw{start_draw()}
|
\S{drawingapi-start-draw} \cw{start_draw()}
|
||||||
|
|
||||||
\c void (*start_draw)(void *handle);
|
\c void (*start_draw)(drawing *dr);
|
||||||
|
|
||||||
This function is called at the start of drawing. It allows the front
|
This function is called at the start of drawing. It allows the front
|
||||||
end to initialise any temporary data required to draw with, such as
|
end to initialise any temporary data required to draw with, such as
|
||||||
@ -2792,7 +2814,7 @@ called unless drawing is attempted.
|
|||||||
|
|
||||||
\S{drawingapi-end-draw} \cw{end_draw()}
|
\S{drawingapi-end-draw} \cw{end_draw()}
|
||||||
|
|
||||||
\c void (*end_draw)(void *handle);
|
\c void (*end_draw)(drawing *dr);
|
||||||
|
|
||||||
This function is called at the end of drawing. It allows the front
|
This function is called at the end of drawing. It allows the front
|
||||||
end to do cleanup tasks such as deallocating device contexts and
|
end to do cleanup tasks such as deallocating device contexts and
|
||||||
@ -2804,7 +2826,7 @@ called unless drawing is attempted.
|
|||||||
|
|
||||||
\S{drawingapi-status-bar} \cw{status_bar()}
|
\S{drawingapi-status-bar} \cw{status_bar()}
|
||||||
|
|
||||||
\c void (*status_bar)(void *handle, const char *text);
|
\c void (*status_bar)(drawing *dr, const char *text);
|
||||||
|
|
||||||
This function behaves exactly like the back end \cw{status_bar()}
|
This function behaves exactly like the back end \cw{status_bar()}
|
||||||
function; see \k{drawing-status-bar}.
|
function; see \k{drawing-status-bar}.
|
||||||
@ -2819,7 +2841,7 @@ called unless drawing is attempted.
|
|||||||
|
|
||||||
\S{drawingapi-blitter-new} \cw{blitter_new()}
|
\S{drawingapi-blitter-new} \cw{blitter_new()}
|
||||||
|
|
||||||
\c blitter *(*blitter_new)(void *handle, int w, int h);
|
\c blitter *(*blitter_new)(drawing *dr, int w, int h);
|
||||||
|
|
||||||
This function behaves exactly like the back end \cw{blitter_new()}
|
This function behaves exactly like the back end \cw{blitter_new()}
|
||||||
function; see \k{drawing-blitter-new}.
|
function; see \k{drawing-blitter-new}.
|
||||||
@ -2830,7 +2852,7 @@ called unless drawing is attempted.
|
|||||||
|
|
||||||
\S{drawingapi-blitter-free} \cw{blitter_free()}
|
\S{drawingapi-blitter-free} \cw{blitter_free()}
|
||||||
|
|
||||||
\c void (*blitter_free)(void *handle, blitter *bl);
|
\c void (*blitter_free)(drawing *dr, blitter *bl);
|
||||||
|
|
||||||
This function behaves exactly like the back end \cw{blitter_free()}
|
This function behaves exactly like the back end \cw{blitter_free()}
|
||||||
function; see \k{drawing-blitter-free}.
|
function; see \k{drawing-blitter-free}.
|
||||||
@ -2841,7 +2863,7 @@ called unless drawing is attempted.
|
|||||||
|
|
||||||
\S{drawingapi-blitter-save} \cw{blitter_save()}
|
\S{drawingapi-blitter-save} \cw{blitter_save()}
|
||||||
|
|
||||||
\c void (*blitter_save)(void *handle, blitter *bl, int x, int y);
|
\c void (*blitter_save)(drawing *dr, blitter *bl, int x, int y);
|
||||||
|
|
||||||
This function behaves exactly like the back end \cw{blitter_save()}
|
This function behaves exactly like the back end \cw{blitter_save()}
|
||||||
function; see \k{drawing-blitter-save}.
|
function; see \k{drawing-blitter-save}.
|
||||||
@ -2852,7 +2874,7 @@ called unless drawing is attempted.
|
|||||||
|
|
||||||
\S{drawingapi-blitter-load} \cw{blitter_load()}
|
\S{drawingapi-blitter-load} \cw{blitter_load()}
|
||||||
|
|
||||||
\c void (*blitter_load)(void *handle, blitter *bl, int x, int y);
|
\c void (*blitter_load)(drawing *dr, blitter *bl, int x, int y);
|
||||||
|
|
||||||
This function behaves exactly like the back end \cw{blitter_load()}
|
This function behaves exactly like the back end \cw{blitter_load()}
|
||||||
function; see \k{drawing-blitter-load}.
|
function; see \k{drawing-blitter-load}.
|
||||||
@ -2863,7 +2885,7 @@ called unless drawing is attempted.
|
|||||||
|
|
||||||
\S{drawingapi-begin-doc} \cw{begin_doc()}
|
\S{drawingapi-begin-doc} \cw{begin_doc()}
|
||||||
|
|
||||||
\c void (*begin_doc)(void *handle, int pages);
|
\c void (*begin_doc)(drawing *dr, int pages);
|
||||||
|
|
||||||
This function is called at the beginning of a printing run. It gives
|
This function is called at the beginning of a printing run. It gives
|
||||||
the front end an opportunity to initialise any required printing
|
the front end an opportunity to initialise any required printing
|
||||||
@ -2875,7 +2897,7 @@ called unless printing is attempted.
|
|||||||
|
|
||||||
\S{drawingapi-begin-page} \cw{begin_page()}
|
\S{drawingapi-begin-page} \cw{begin_page()}
|
||||||
|
|
||||||
\c void (*begin_page)(void *handle, int number);
|
\c void (*begin_page)(drawing *dr, int number);
|
||||||
|
|
||||||
This function is called during printing, at the beginning of each
|
This function is called during printing, at the beginning of each
|
||||||
page. It gives the page number (numbered from 1 rather than 0, so
|
page. It gives the page number (numbered from 1 rather than 0, so
|
||||||
@ -2887,7 +2909,7 @@ called unless printing is attempted.
|
|||||||
|
|
||||||
\S{drawingapi-begin-puzzle} \cw{begin_puzzle()}
|
\S{drawingapi-begin-puzzle} \cw{begin_puzzle()}
|
||||||
|
|
||||||
\c void (*begin_puzzle)(void *handle, float xm, float xc,
|
\c void (*begin_puzzle)(drawing *dr, float xm, float xc,
|
||||||
\c float ym, float yc, int pw, int ph, float wmm);
|
\c float ym, float yc, int pw, int ph, float wmm);
|
||||||
|
|
||||||
This function is called during printing, just before printing a
|
This function is called during printing, just before printing a
|
||||||
@ -2930,7 +2952,7 @@ called unless printing is attempted.
|
|||||||
|
|
||||||
\S{drawingapi-end-puzzle} \cw{end_puzzle()}
|
\S{drawingapi-end-puzzle} \cw{end_puzzle()}
|
||||||
|
|
||||||
\c void (*end_puzzle)(void *handle);
|
\c void (*end_puzzle)(drawing *dr);
|
||||||
|
|
||||||
This function is called after the printing of a specific puzzle is
|
This function is called after the printing of a specific puzzle is
|
||||||
complete.
|
complete.
|
||||||
@ -2941,7 +2963,7 @@ called unless printing is attempted.
|
|||||||
|
|
||||||
\S{drawingapi-end-page} \cw{end_page()}
|
\S{drawingapi-end-page} \cw{end_page()}
|
||||||
|
|
||||||
\c void (*end_page)(void *handle, int number);
|
\c void (*end_page)(drawing *dr, int number);
|
||||||
|
|
||||||
This function is called after the printing of a page is finished.
|
This function is called after the printing of a page is finished.
|
||||||
|
|
||||||
@ -2951,7 +2973,7 @@ called unless printing is attempted.
|
|||||||
|
|
||||||
\S{drawingapi-end-doc} \cw{end_doc()}
|
\S{drawingapi-end-doc} \cw{end_doc()}
|
||||||
|
|
||||||
\c void (*end_doc)(void *handle);
|
\c void (*end_doc)(drawing *dr);
|
||||||
|
|
||||||
This function is called after the printing of the entire document is
|
This function is called after the printing of the entire document is
|
||||||
finished. This is the moment to close files, send things to the
|
finished. This is the moment to close files, send things to the
|
||||||
@ -2963,7 +2985,7 @@ called unless printing is attempted.
|
|||||||
|
|
||||||
\S{drawingapi-line-width} \cw{line_width()}
|
\S{drawingapi-line-width} \cw{line_width()}
|
||||||
|
|
||||||
\c void (*line_width)(void *handle, float width);
|
\c void (*line_width)(drawing *dr, float width);
|
||||||
|
|
||||||
This function is called to set the line thickness, during printing
|
This function is called to set the line thickness, during printing
|
||||||
only. Note that the width is a \cw{float} here, where it was an
|
only. Note that the width is a \cw{float} here, where it was an
|
||||||
@ -2979,7 +3001,7 @@ called unless printing is attempted.
|
|||||||
|
|
||||||
\S{drawingapi-line-dotted} \cw{line_dotted()}
|
\S{drawingapi-line-dotted} \cw{line_dotted()}
|
||||||
|
|
||||||
\c void (*line_dotted)(void *handle, bool dotted);
|
\c void (*line_dotted)(drawing *dr, bool dotted);
|
||||||
|
|
||||||
This function is called to toggle drawing of dotted lines, during
|
This function is called to toggle drawing of dotted lines, during
|
||||||
printing only.
|
printing only.
|
||||||
@ -2990,7 +3012,7 @@ called unless printing is attempted.
|
|||||||
|
|
||||||
\S{drawingapi-text-fallback} \cw{text_fallback()}
|
\S{drawingapi-text-fallback} \cw{text_fallback()}
|
||||||
|
|
||||||
\c char *(*text_fallback)(void *handle, const char *const *strings,
|
\c char *(*text_fallback)(drawing *dr, const char *const *strings,
|
||||||
\c int nstrings);
|
\c int nstrings);
|
||||||
|
|
||||||
This function behaves exactly like the back end \cw{text_fallback()}
|
This function behaves exactly like the back end \cw{text_fallback()}
|
||||||
@ -3013,9 +3035,10 @@ implement. They are described in this section.
|
|||||||
\c void *handle);
|
\c void *handle);
|
||||||
|
|
||||||
This function creates a drawing object. It is passed a
|
This function creates a drawing object. It is passed a
|
||||||
\c{drawing_api}, which is a structure containing nothing but
|
\c{drawing_api}, which is a structure containing function pointers and
|
||||||
function pointers; and also a \cq{void *} handle. The handle is
|
a version field; and also a \cq{void *} handle. The handle is stored
|
||||||
passed back to each function pointer when it is called.
|
in the drawing object, from where it may be accessed by each function
|
||||||
|
pointer when it is called.
|
||||||
|
|
||||||
The \c{midend} parameter is used for rewriting the status bar
|
The \c{midend} parameter is used for rewriting the status bar
|
||||||
contents: \cw{status_bar()} (see \k{drawing-status-bar}) has to call
|
contents: \cw{status_bar()} (see \k{drawing-status-bar}) has to call
|
||||||
@ -3024,6 +3047,10 @@ If the drawing object is to be used only for printing, or if the
|
|||||||
game is known not to call \cw{status_bar()}, this parameter may be
|
game is known not to call \cw{status_bar()}, this parameter may be
|
||||||
\cw{NULL}.
|
\cw{NULL}.
|
||||||
|
|
||||||
|
A fatal error is produced if the \cw{version} field of the
|
||||||
|
\c{drawing_api} does not match the expected version (see
|
||||||
|
\k{drawingapi-version} for the expected version number).
|
||||||
|
|
||||||
\S{drawing-free} \cw{drawing_free()}
|
\S{drawing-free} \cw{drawing_free()}
|
||||||
|
|
||||||
\c void drawing_free(drawing *dr);
|
\c void drawing_free(drawing *dr);
|
||||||
@ -5351,6 +5378,15 @@ argument is respectively less than, equal to, or greater than the
|
|||||||
second. This function is intended to be passed to \c{qsort()} for
|
second. This function is intended to be passed to \c{qsort()} for
|
||||||
sorting ints in ascending order.
|
sorting ints in ascending order.
|
||||||
|
|
||||||
|
\S{utils-get-handle-as-type} \cw{GET_HANDLE_AS_TYPE()}
|
||||||
|
|
||||||
|
\c #define GET_HANDLE_AS_TYPE(dr, type) ((type*)((dr)->handle))
|
||||||
|
|
||||||
|
This macro, defined in the main Puzzles header file, retrieves the
|
||||||
|
\c{handle} field from a \c{drawing *} pointer and casts it to \c{type
|
||||||
|
*}. It is intended for use in implementations of drawing API
|
||||||
|
functions, where this operation is idiomatic.
|
||||||
|
|
||||||
\C{writing} How to write a new puzzle
|
\C{writing} How to write a new puzzle
|
||||||
|
|
||||||
This chapter gives a guide to how to actually write a new puzzle:
|
This chapter gives a guide to how to actually write a new puzzle:
|
||||||
|
196
drawing.c
196
drawing.c
@ -42,9 +42,12 @@ struct print_colour {
|
|||||||
float grey;
|
float grey;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct drawing {
|
typedef struct drawing_internal {
|
||||||
const drawing_api *api;
|
/* we implement data hiding by casting `struct drawing*` pointers
|
||||||
void *handle;
|
* to `struct drawing_internal*` */
|
||||||
|
struct drawing pub;
|
||||||
|
|
||||||
|
/* private data */
|
||||||
struct print_colour *colours;
|
struct print_colour *colours;
|
||||||
int ncolours, coloursize;
|
int ncolours, coloursize;
|
||||||
float scale;
|
float scale;
|
||||||
@ -52,53 +55,70 @@ struct drawing {
|
|||||||
* this may set it to NULL. */
|
* this may set it to NULL. */
|
||||||
midend *me;
|
midend *me;
|
||||||
char *laststatus;
|
char *laststatus;
|
||||||
};
|
} drawing_internal;
|
||||||
|
|
||||||
|
#define PRIVATE_CAST(dr) ((drawing_internal*)(dr))
|
||||||
|
#define PUBLIC_CAST(dri) ((drawing*)(dri))
|
||||||
|
|
||||||
|
/* See puzzles.h for a description of the version number. */
|
||||||
|
#define DRAWING_API_VERSION 1
|
||||||
|
|
||||||
drawing *drawing_new(const drawing_api *api, midend *me, void *handle)
|
drawing *drawing_new(const drawing_api *api, midend *me, void *handle)
|
||||||
{
|
{
|
||||||
drawing *dr = snew(drawing);
|
if(api->version != DRAWING_API_VERSION) {
|
||||||
dr->api = api;
|
fatal("Drawing API version mismatch: expected: %d, actual: %d\n", DRAWING_API_VERSION, api->version);
|
||||||
dr->handle = handle;
|
/* shouldn't get here */
|
||||||
dr->colours = NULL;
|
return NULL;
|
||||||
dr->ncolours = dr->coloursize = 0;
|
}
|
||||||
dr->scale = 1.0F;
|
|
||||||
dr->me = me;
|
drawing_internal *dri = snew(drawing_internal);
|
||||||
dr->laststatus = NULL;
|
dri->pub.api = api;
|
||||||
return dr;
|
dri->pub.handle = handle;
|
||||||
|
dri->colours = NULL;
|
||||||
|
dri->ncolours = dri->coloursize = 0;
|
||||||
|
dri->scale = 1.0F;
|
||||||
|
dri->me = me;
|
||||||
|
dri->laststatus = NULL;
|
||||||
|
return PUBLIC_CAST(dri);
|
||||||
}
|
}
|
||||||
|
|
||||||
void drawing_free(drawing *dr)
|
void drawing_free(drawing *dr)
|
||||||
{
|
{
|
||||||
sfree(dr->laststatus);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
sfree(dr->colours);
|
sfree(dri->laststatus);
|
||||||
sfree(dr);
|
sfree(dri->colours);
|
||||||
|
sfree(dri);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_text(drawing *dr, int x, int y, int fonttype, int fontsize,
|
void draw_text(drawing *dr, int x, int y, int fonttype, int fontsize,
|
||||||
int align, int colour, const char *text)
|
int align, int colour, const char *text)
|
||||||
{
|
{
|
||||||
dr->api->draw_text(dr->handle, x, y, fonttype, fontsize, align,
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
colour, text);
|
dri->pub.api->draw_text(dr, x, y, fonttype, fontsize, align,
|
||||||
|
colour, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_rect(drawing *dr, int x, int y, int w, int h, int colour)
|
void draw_rect(drawing *dr, int x, int y, int w, int h, int colour)
|
||||||
{
|
{
|
||||||
dr->api->draw_rect(dr->handle, x, y, w, h, colour);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->draw_rect(dr, x, y, w, h, colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour)
|
void draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour)
|
||||||
{
|
{
|
||||||
dr->api->draw_line(dr->handle, x1, y1, x2, y2, colour);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->draw_line(dr, x1, y1, x2, y2, colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_thick_line(drawing *dr, float thickness,
|
void draw_thick_line(drawing *dr, float thickness,
|
||||||
float x1, float y1, float x2, float y2, int colour)
|
float x1, float y1, float x2, float y2, int colour)
|
||||||
{
|
{
|
||||||
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
if (thickness < 1.0F)
|
if (thickness < 1.0F)
|
||||||
thickness = 1.0F;
|
thickness = 1.0F;
|
||||||
if (dr->api->draw_thick_line) {
|
if (dri->pub.api->draw_thick_line) {
|
||||||
dr->api->draw_thick_line(dr->handle, thickness,
|
dri->pub.api->draw_thick_line(dr, thickness,
|
||||||
x1, y1, x2, y2, colour);
|
x1, y1, x2, y2, colour);
|
||||||
} else {
|
} else {
|
||||||
/* We'll fake it up with a filled polygon. The tweak to the
|
/* We'll fake it up with a filled polygon. The tweak to the
|
||||||
* thickness empirically compensates for rounding errors, because
|
* thickness empirically compensates for rounding errors, because
|
||||||
@ -117,59 +137,67 @@ void draw_thick_line(drawing *dr, float thickness,
|
|||||||
p[5] = y2 - tvhatx;
|
p[5] = y2 - tvhatx;
|
||||||
p[6] = x1 + tvhaty;
|
p[6] = x1 + tvhaty;
|
||||||
p[7] = y1 - tvhatx;
|
p[7] = y1 - tvhatx;
|
||||||
dr->api->draw_polygon(dr->handle, p, 4, colour, colour);
|
dri->pub.api->draw_polygon(dr, p, 4, colour, colour);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_polygon(drawing *dr, const int *coords, int npoints,
|
void draw_polygon(drawing *dr, const int *coords, int npoints,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
dr->api->draw_polygon(dr->handle, coords, npoints, fillcolour,
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
outlinecolour);
|
dri->pub.api->draw_polygon(dr, coords, npoints, fillcolour,
|
||||||
|
outlinecolour);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_circle(drawing *dr, int cx, int cy, int radius,
|
void draw_circle(drawing *dr, int cx, int cy, int radius,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
dr->api->draw_circle(dr->handle, cx, cy, radius, fillcolour,
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
outlinecolour);
|
dri->pub.api->draw_circle(dr, cx, cy, radius, fillcolour,
|
||||||
|
outlinecolour);
|
||||||
}
|
}
|
||||||
|
|
||||||
void draw_update(drawing *dr, int x, int y, int w, int h)
|
void draw_update(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
if (dr->api->draw_update)
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
dr->api->draw_update(dr->handle, x, y, w, h);
|
if (dri->pub.api->draw_update)
|
||||||
|
dri->pub.api->draw_update(dr, x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clip(drawing *dr, int x, int y, int w, int h)
|
void clip(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
dr->api->clip(dr->handle, x, y, w, h);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->clip(dr, x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void unclip(drawing *dr)
|
void unclip(drawing *dr)
|
||||||
{
|
{
|
||||||
dr->api->unclip(dr->handle);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->unclip(dr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void start_draw(drawing *dr)
|
void start_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
dr->api->start_draw(dr->handle);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->start_draw(dr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void end_draw(drawing *dr)
|
void end_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
dr->api->end_draw(dr->handle);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->end_draw(dr);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *text_fallback(drawing *dr, const char *const *strings, int nstrings)
|
char *text_fallback(drawing *dr, const char *const *strings, int nstrings)
|
||||||
{
|
{
|
||||||
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* If the drawing implementation provides one of these, use it.
|
* If the drawing implementation provides one of these, use it.
|
||||||
*/
|
*/
|
||||||
if (dr && dr->api->text_fallback)
|
if (dr && dri->pub.api->text_fallback)
|
||||||
return dr->api->text_fallback(dr->handle, strings, nstrings);
|
return dri->pub.api->text_fallback(dr, strings, nstrings);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Otherwise, do the simple thing and just pick the first string
|
* Otherwise, do the simple thing and just pick the first string
|
||||||
@ -196,18 +224,19 @@ char *text_fallback(drawing *dr, const char *const *strings, int nstrings)
|
|||||||
|
|
||||||
void status_bar(drawing *dr, const char *text)
|
void status_bar(drawing *dr, const char *text)
|
||||||
{
|
{
|
||||||
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
char *rewritten;
|
char *rewritten;
|
||||||
|
|
||||||
if (!dr->api->status_bar)
|
if (!dri->pub.api->status_bar)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
assert(dr->me);
|
assert(dri->me);
|
||||||
|
|
||||||
rewritten = midend_rewrite_statusbar(dr->me, text);
|
rewritten = midend_rewrite_statusbar(dri->me, text);
|
||||||
if (!dr->laststatus || strcmp(rewritten, dr->laststatus)) {
|
if (!dri->laststatus || strcmp(rewritten, dri->laststatus)) {
|
||||||
dr->api->status_bar(dr->handle, rewritten);
|
dri->pub.api->status_bar(dr, rewritten);
|
||||||
sfree(dr->laststatus);
|
sfree(dri->laststatus);
|
||||||
dr->laststatus = rewritten;
|
dri->laststatus = rewritten;
|
||||||
} else {
|
} else {
|
||||||
sfree(rewritten);
|
sfree(rewritten);
|
||||||
}
|
}
|
||||||
@ -215,74 +244,85 @@ void status_bar(drawing *dr, const char *text)
|
|||||||
|
|
||||||
blitter *blitter_new(drawing *dr, int w, int h)
|
blitter *blitter_new(drawing *dr, int w, int h)
|
||||||
{
|
{
|
||||||
return dr->api->blitter_new(dr->handle, w, h);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
return dri->pub.api->blitter_new(dr, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
void blitter_free(drawing *dr, blitter *bl)
|
void blitter_free(drawing *dr, blitter *bl)
|
||||||
{
|
{
|
||||||
dr->api->blitter_free(dr->handle, bl);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->blitter_free(dr, bl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void blitter_save(drawing *dr, blitter *bl, int x, int y)
|
void blitter_save(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
dr->api->blitter_save(dr->handle, bl, x, y);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->blitter_save(dr, bl, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void blitter_load(drawing *dr, blitter *bl, int x, int y)
|
void blitter_load(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
dr->api->blitter_load(dr->handle, bl, x, y);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->blitter_load(dr, bl, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_begin_doc(drawing *dr, int pages)
|
void print_begin_doc(drawing *dr, int pages)
|
||||||
{
|
{
|
||||||
dr->api->begin_doc(dr->handle, pages);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->begin_doc(dr, pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_begin_page(drawing *dr, int number)
|
void print_begin_page(drawing *dr, int number)
|
||||||
{
|
{
|
||||||
dr->api->begin_page(dr->handle, number);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->begin_page(dr, number);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_begin_puzzle(drawing *dr, float xm, float xc,
|
void print_begin_puzzle(drawing *dr, float xm, float xc,
|
||||||
float ym, float yc, int pw, int ph, float wmm,
|
float ym, float yc, int pw, int ph, float wmm,
|
||||||
float scale)
|
float scale)
|
||||||
{
|
{
|
||||||
dr->scale = scale;
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
dr->ncolours = 0;
|
dri->scale = scale;
|
||||||
dr->api->begin_puzzle(dr->handle, xm, xc, ym, yc, pw, ph, wmm);
|
dri->ncolours = 0;
|
||||||
|
dri->pub.api->begin_puzzle(dr, xm, xc, ym, yc, pw, ph, wmm);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_end_puzzle(drawing *dr)
|
void print_end_puzzle(drawing *dr)
|
||||||
{
|
{
|
||||||
dr->api->end_puzzle(dr->handle);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
dr->scale = 1.0F;
|
dri->pub.api->end_puzzle(dr);
|
||||||
|
dri->scale = 1.0F;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_end_page(drawing *dr, int number)
|
void print_end_page(drawing *dr, int number)
|
||||||
{
|
{
|
||||||
dr->api->end_page(dr->handle, number);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->end_page(dr, number);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_end_doc(drawing *dr)
|
void print_end_doc(drawing *dr)
|
||||||
{
|
{
|
||||||
dr->api->end_doc(dr->handle);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->end_doc(dr);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_get_colour(drawing *dr, int colour, bool printing_in_colour,
|
void print_get_colour(drawing *dr, int colour, bool printing_in_colour,
|
||||||
int *hatch, float *r, float *g, float *b)
|
int *hatch, float *r, float *g, float *b)
|
||||||
{
|
{
|
||||||
assert(colour >= 0 && colour < dr->ncolours);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
if (dr->colours[colour].hatch_when == 2 ||
|
assert(colour >= 0 && colour < dri->ncolours);
|
||||||
(dr->colours[colour].hatch_when == 1 && !printing_in_colour)) {
|
if (dri->colours[colour].hatch_when == 2 ||
|
||||||
*hatch = dr->colours[colour].hatch;
|
(dri->colours[colour].hatch_when == 1 && !printing_in_colour)) {
|
||||||
|
*hatch = dri->colours[colour].hatch;
|
||||||
} else {
|
} else {
|
||||||
*hatch = -1;
|
*hatch = -1;
|
||||||
if (printing_in_colour) {
|
if (printing_in_colour) {
|
||||||
*r = dr->colours[colour].r;
|
*r = dri->colours[colour].r;
|
||||||
*g = dr->colours[colour].g;
|
*g = dri->colours[colour].g;
|
||||||
*b = dr->colours[colour].b;
|
*b = dri->colours[colour].b;
|
||||||
} else {
|
} else {
|
||||||
*r = *g = *b = dr->colours[colour].grey;
|
*r = *g = *b = dri->colours[colour].grey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -290,18 +330,19 @@ void print_get_colour(drawing *dr, int colour, bool printing_in_colour,
|
|||||||
static int print_generic_colour(drawing *dr, 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)
|
float grey, int hatch, int hatch_when)
|
||||||
{
|
{
|
||||||
if (dr->ncolours >= dr->coloursize) {
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
dr->coloursize = dr->ncolours + 16;
|
if (dri->ncolours >= dri->coloursize) {
|
||||||
dr->colours = sresize(dr->colours, dr->coloursize,
|
dri->coloursize = dri->ncolours + 16;
|
||||||
|
dri->colours = sresize(dri->colours, dri->coloursize,
|
||||||
struct print_colour);
|
struct print_colour);
|
||||||
}
|
}
|
||||||
dr->colours[dr->ncolours].hatch = hatch;
|
dri->colours[dri->ncolours].hatch = hatch;
|
||||||
dr->colours[dr->ncolours].hatch_when = hatch_when;
|
dri->colours[dri->ncolours].hatch_when = hatch_when;
|
||||||
dr->colours[dr->ncolours].r = r;
|
dri->colours[dri->ncolours].r = r;
|
||||||
dr->colours[dr->ncolours].g = g;
|
dri->colours[dri->ncolours].g = g;
|
||||||
dr->colours[dr->ncolours].b = b;
|
dri->colours[dri->ncolours].b = b;
|
||||||
dr->colours[dr->ncolours].grey = grey;
|
dri->colours[dri->ncolours].grey = grey;
|
||||||
return dr->ncolours++;
|
return dri->ncolours++;
|
||||||
}
|
}
|
||||||
|
|
||||||
int print_mono_colour(drawing *dr, int grey)
|
int print_mono_colour(drawing *dr, int grey)
|
||||||
@ -336,6 +377,8 @@ 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)
|
||||||
{
|
{
|
||||||
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* I don't think it's entirely sensible to have line widths be
|
* I don't think it's entirely sensible to have line widths be
|
||||||
* entirely relative to the puzzle size; there is a point
|
* entirely relative to the puzzle size; there is a point
|
||||||
@ -348,10 +391,11 @@ void print_line_width(drawing *dr, int width)
|
|||||||
* _square root_ of the main puzzle scale. Double the puzzle
|
* _square root_ of the main puzzle scale. Double the puzzle
|
||||||
* size, and the line width multiplies by 1.4.
|
* size, and the line width multiplies by 1.4.
|
||||||
*/
|
*/
|
||||||
dr->api->line_width(dr->handle, (float)sqrt(dr->scale) * width);
|
dri->pub.api->line_width(dr, (float)sqrt(dri->scale) * width);
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_line_dotted(drawing *dr, bool dotted)
|
void print_line_dotted(drawing *dr, bool dotted)
|
||||||
{
|
{
|
||||||
dr->api->line_dotted(dr->handle, dotted);
|
drawing_internal *dri = PRIVATE_CAST(dr);
|
||||||
|
dri->pub.api->line_dotted(dr, dotted);
|
||||||
}
|
}
|
||||||
|
35
emcc.c
35
emcc.c
@ -456,22 +456,22 @@ static void ids_changed(void *ignored)
|
|||||||
* drawing functions. (Well, half of it; the other half is on the JS
|
* drawing functions. (Well, half of it; the other half is on the JS
|
||||||
* side.)
|
* side.)
|
||||||
*/
|
*/
|
||||||
static void js_start_draw(void *handle)
|
static void js_start_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
js_canvas_start_draw();
|
js_canvas_start_draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_clip(void *handle, int x, int y, int w, int h)
|
static void js_clip(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
js_canvas_clip_rect(x, y, w, h);
|
js_canvas_clip_rect(x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_unclip(void *handle)
|
static void js_unclip(drawing *dr)
|
||||||
{
|
{
|
||||||
js_canvas_unclip();
|
js_canvas_unclip();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_draw_text(void *handle, int x, int y, int fonttype,
|
static void js_draw_text(drawing *dr, int x, int y, int fonttype,
|
||||||
int fontsize, int align, int colour,
|
int fontsize, int align, int colour,
|
||||||
const char *text)
|
const char *text)
|
||||||
{
|
{
|
||||||
@ -491,31 +491,31 @@ static void js_draw_text(void *handle, int x, int y, int fonttype,
|
|||||||
fontsize, fonttype == FONT_FIXED, text);
|
fontsize, fonttype == FONT_FIXED, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_draw_rect(void *handle, int x, int y, int w, int h, int colour)
|
static void js_draw_rect(drawing *dr, int x, int y, int w, int h, int colour)
|
||||||
{
|
{
|
||||||
js_canvas_draw_rect(x, y, w, h, colour);
|
js_canvas_draw_rect(x, y, w, h, colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_draw_line(void *handle, int x1, int y1, int x2, int y2,
|
static void js_draw_line(drawing *dr, int x1, int y1, int x2, int y2,
|
||||||
int colour)
|
int colour)
|
||||||
{
|
{
|
||||||
js_canvas_draw_line(x1, y1, x2, y2, 1, colour);
|
js_canvas_draw_line(x1, y1, x2, y2, 1, colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_draw_thick_line(void *handle, float thickness,
|
static void js_draw_thick_line(drawing *dr, float thickness,
|
||||||
float x1, float y1, float x2, float y2,
|
float x1, float y1, float x2, float y2,
|
||||||
int colour)
|
int colour)
|
||||||
{
|
{
|
||||||
js_canvas_draw_line(x1, y1, x2, y2, thickness, colour);
|
js_canvas_draw_line(x1, y1, x2, y2, thickness, colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_draw_poly(void *handle, const int *coords, int npoints,
|
static void js_draw_poly(drawing *dr, const int *coords, int npoints,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
js_canvas_draw_poly(coords, npoints, fillcolour, outlinecolour);
|
js_canvas_draw_poly(coords, npoints, fillcolour, outlinecolour);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_draw_circle(void *handle, int cx, int cy, int radius,
|
static void js_draw_circle(drawing *dr, int cx, int cy, int radius,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
js_canvas_draw_circle(cx, cy, radius, fillcolour, outlinecolour);
|
js_canvas_draw_circle(cx, cy, radius, fillcolour, outlinecolour);
|
||||||
@ -526,7 +526,7 @@ struct blitter {
|
|||||||
int w, h; /* easier to retain here */
|
int w, h; /* easier to retain here */
|
||||||
};
|
};
|
||||||
|
|
||||||
static blitter *js_blitter_new(void *handle, int w, int h)
|
static blitter *js_blitter_new(drawing *dr, int w, int h)
|
||||||
{
|
{
|
||||||
blitter *bl = snew(blitter);
|
blitter *bl = snew(blitter);
|
||||||
bl->w = w;
|
bl->w = w;
|
||||||
@ -535,7 +535,7 @@ static blitter *js_blitter_new(void *handle, int w, int h)
|
|||||||
return bl;
|
return bl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_blitter_free(void *handle, blitter *bl)
|
static void js_blitter_free(drawing *dr, blitter *bl)
|
||||||
{
|
{
|
||||||
js_canvas_free_blitter(bl->id);
|
js_canvas_free_blitter(bl->id);
|
||||||
sfree(bl);
|
sfree(bl);
|
||||||
@ -569,7 +569,7 @@ static void trim_rect(int *x, int *y, int *w, int *h)
|
|||||||
*h = y1 - y0;
|
*h = y1 - y0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_blitter_save(void *handle, blitter *bl, int x, int y)
|
static void js_blitter_save(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
int w = bl->w, h = bl->h;
|
int w = bl->w, h = bl->h;
|
||||||
trim_rect(&x, &y, &w, &h);
|
trim_rect(&x, &y, &w, &h);
|
||||||
@ -577,7 +577,7 @@ static void js_blitter_save(void *handle, blitter *bl, int x, int y)
|
|||||||
js_canvas_copy_to_blitter(bl->id, x, y, w, h);
|
js_canvas_copy_to_blitter(bl->id, x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_blitter_load(void *handle, blitter *bl, int x, int y)
|
static void js_blitter_load(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
int w = bl->w, h = bl->h;
|
int w = bl->w, h = bl->h;
|
||||||
trim_rect(&x, &y, &w, &h);
|
trim_rect(&x, &y, &w, &h);
|
||||||
@ -585,30 +585,31 @@ static void js_blitter_load(void *handle, blitter *bl, int x, int y)
|
|||||||
js_canvas_copy_from_blitter(bl->id, x, y, w, h);
|
js_canvas_copy_from_blitter(bl->id, x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_draw_update(void *handle, int x, int y, int w, int h)
|
static void js_draw_update(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
trim_rect(&x, &y, &w, &h);
|
trim_rect(&x, &y, &w, &h);
|
||||||
if (w > 0 && h > 0)
|
if (w > 0 && h > 0)
|
||||||
js_canvas_draw_update(x, y, w, h);
|
js_canvas_draw_update(x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_end_draw(void *handle)
|
static void js_end_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
js_canvas_end_draw();
|
js_canvas_end_draw();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void js_status_bar(void *handle, const char *text)
|
static void js_status_bar(drawing *dr, const char *text)
|
||||||
{
|
{
|
||||||
js_canvas_set_statusbar(text);
|
js_canvas_set_statusbar(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *js_text_fallback(void *handle, const char *const *strings,
|
static char *js_text_fallback(drawing *dr, const char *const *strings,
|
||||||
int nstrings)
|
int nstrings)
|
||||||
{
|
{
|
||||||
return dupstr(strings[0]); /* Emscripten has no trouble with UTF-8 */
|
return dupstr(strings[0]); /* Emscripten has no trouble with UTF-8 */
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct drawing_api js_drawing = {
|
static const struct drawing_api js_drawing = {
|
||||||
|
1,
|
||||||
js_draw_text,
|
js_draw_text,
|
||||||
js_draw_rect,
|
js_draw_rect,
|
||||||
js_draw_line,
|
js_draw_line,
|
||||||
|
@ -65,7 +65,7 @@ static const char *fuzz_one(bool (*readfn)(void *, void *, int), void *rctx,
|
|||||||
char *gamename;
|
char *gamename;
|
||||||
int i, w, h;
|
int i, w, h;
|
||||||
const game *ourgame = NULL;
|
const game *ourgame = NULL;
|
||||||
static const drawing_api drapi = { NULL };
|
static const drawing_api drapi = { 1, NULL };
|
||||||
midend *me;
|
midend *me;
|
||||||
|
|
||||||
err = identify_game(&gamename, readfn, rctx);
|
err = identify_game(&gamename, readfn, rctx);
|
||||||
|
89
gtk.c
89
gtk.c
@ -329,9 +329,9 @@ void frontend_default_colour(frontend *fe, float *output)
|
|||||||
output[0] = output[1] = output[2] = 0.9F;
|
output[0] = output[1] = output[2] = 0.9F;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_status_bar(void *handle, const char *text)
|
static void gtk_status_bar(drawing *dr, const char *text)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
|
|
||||||
if (fe->headless)
|
if (fe->headless)
|
||||||
return;
|
return;
|
||||||
@ -1164,9 +1164,9 @@ static void align_and_draw_text(int index, int align, int x, int y,
|
|||||||
* The exported drawing functions.
|
* The exported drawing functions.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void gtk_start_draw(void *handle)
|
static void gtk_start_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
fe->bbox_l = fe->w;
|
fe->bbox_l = fe->w;
|
||||||
fe->bbox_r = 0;
|
fe->bbox_r = 0;
|
||||||
fe->bbox_u = fe->h;
|
fe->bbox_u = fe->h;
|
||||||
@ -1174,23 +1174,23 @@ static void gtk_start_draw(void *handle)
|
|||||||
setup_drawing(fe);
|
setup_drawing(fe);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_clip(void *handle, int x, int y, int w, int h)
|
static void gtk_clip(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
do_clip(fe, x, y, w, h);
|
do_clip(fe, x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_unclip(void *handle)
|
static void gtk_unclip(drawing *dr)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
do_unclip(fe);
|
do_unclip(fe);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_draw_text(void *handle, int x, int y, int fonttype,
|
static void gtk_draw_text(drawing *dr, int x, int y, int fonttype,
|
||||||
int fontsize, int align, int colour,
|
int fontsize, int align, int colour,
|
||||||
const char *text)
|
const char *text)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1220,45 +1220,45 @@ static void gtk_draw_text(void *handle, int x, int y, int fonttype,
|
|||||||
align_and_draw_text(fe, i, align, x, y, text);
|
align_and_draw_text(fe, i, align, x, y, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_draw_rect(void *handle, int x, int y, int w, int h, int colour)
|
static void gtk_draw_rect(drawing *dr, int x, int y, int w, int h, int colour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
fe->dr_api->set_colour(fe, colour);
|
fe->dr_api->set_colour(fe, colour);
|
||||||
do_draw_rect(fe, x, y, w, h);
|
do_draw_rect(fe, x, y, w, h);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_draw_line(void *handle, int x1, int y1, int x2, int y2,
|
static void gtk_draw_line(drawing *dr, int x1, int y1, int x2, int y2,
|
||||||
int colour)
|
int colour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
fe->dr_api->set_colour(fe, colour);
|
fe->dr_api->set_colour(fe, colour);
|
||||||
do_draw_line(fe, x1, y1, x2, y2);
|
do_draw_line(fe, x1, y1, x2, y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_draw_thick_line(void *handle, float thickness,
|
static void gtk_draw_thick_line(drawing *dr, float thickness,
|
||||||
float x1, float y1, float x2, float y2,
|
float x1, float y1, float x2, float y2,
|
||||||
int colour)
|
int colour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
fe->dr_api->set_colour(fe, colour);
|
fe->dr_api->set_colour(fe, colour);
|
||||||
do_draw_thick_line(fe, thickness, x1, y1, x2, y2);
|
do_draw_thick_line(fe, thickness, x1, y1, x2, y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_draw_poly(void *handle, const int *coords, int npoints,
|
static void gtk_draw_poly(drawing *dr, const int *coords, int npoints,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
do_draw_poly(fe, coords, npoints, fillcolour, outlinecolour);
|
do_draw_poly(fe, coords, npoints, fillcolour, outlinecolour);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_draw_circle(void *handle, int cx, int cy, int radius,
|
static void gtk_draw_circle(drawing *dr, int cx, int cy, int radius,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
do_draw_circle(fe, cx, cy, radius, fillcolour, outlinecolour);
|
do_draw_circle(fe, cx, cy, radius, fillcolour, outlinecolour);
|
||||||
}
|
}
|
||||||
|
|
||||||
static blitter *gtk_blitter_new(void *handle, int w, int h)
|
static blitter *gtk_blitter_new(drawing *dr, int w, int h)
|
||||||
{
|
{
|
||||||
blitter *bl = snew(blitter);
|
blitter *bl = snew(blitter);
|
||||||
setup_blitter(bl, w, h);
|
setup_blitter(bl, w, h);
|
||||||
@ -1267,23 +1267,23 @@ static blitter *gtk_blitter_new(void *handle, int w, int h)
|
|||||||
return bl;
|
return bl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_blitter_free(void *handle, blitter *bl)
|
static void gtk_blitter_free(drawing *dr, blitter *bl)
|
||||||
{
|
{
|
||||||
teardown_blitter(bl);
|
teardown_blitter(bl);
|
||||||
sfree(bl);
|
sfree(bl);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_blitter_save(void *handle, blitter *bl, int x, int y)
|
static void gtk_blitter_save(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
do_blitter_save(fe, bl, x, y);
|
do_blitter_save(fe, bl, x, y);
|
||||||
bl->x = x;
|
bl->x = x;
|
||||||
bl->y = y;
|
bl->y = y;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_blitter_load(void *handle, blitter *bl, int x, int y)
|
static void gtk_blitter_load(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
if (x == BLITTER_FROMSAVED && y == BLITTER_FROMSAVED) {
|
if (x == BLITTER_FROMSAVED && y == BLITTER_FROMSAVED) {
|
||||||
x = bl->x;
|
x = bl->x;
|
||||||
y = bl->y;
|
y = bl->y;
|
||||||
@ -1291,18 +1291,18 @@ static void gtk_blitter_load(void *handle, blitter *bl, int x, int y)
|
|||||||
do_blitter_load(fe, bl, x, y);
|
do_blitter_load(fe, bl, x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_draw_update(void *handle, int x, int y, int w, int h)
|
static void gtk_draw_update(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
if (fe->bbox_l > x ) fe->bbox_l = x ;
|
if (fe->bbox_l > x ) fe->bbox_l = x ;
|
||||||
if (fe->bbox_r < x+w) fe->bbox_r = x+w;
|
if (fe->bbox_r < x+w) fe->bbox_r = x+w;
|
||||||
if (fe->bbox_u > y ) fe->bbox_u = y ;
|
if (fe->bbox_u > y ) fe->bbox_u = y ;
|
||||||
if (fe->bbox_d < y+h) fe->bbox_d = y+h;
|
if (fe->bbox_d < y+h) fe->bbox_d = y+h;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_end_draw(void *handle)
|
static void gtk_end_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
|
|
||||||
teardown_drawing(fe);
|
teardown_drawing(fe);
|
||||||
|
|
||||||
@ -1324,7 +1324,7 @@ static void gtk_end_draw(void *handle)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef USE_PANGO
|
#ifdef USE_PANGO
|
||||||
static char *gtk_text_fallback(void *handle, const char *const *strings,
|
static char *gtk_text_fallback(drawing *dr, const char *const *strings,
|
||||||
int nstrings)
|
int nstrings)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -1336,20 +1336,20 @@ static char *gtk_text_fallback(void *handle, const char *const *strings,
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef USE_PRINTING
|
#ifdef USE_PRINTING
|
||||||
static void gtk_begin_doc(void *handle, int pages)
|
static void gtk_begin_doc(drawing *dr, int pages)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
gtk_print_operation_set_n_pages(fe->printop, pages);
|
gtk_print_operation_set_n_pages(fe->printop, pages);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_begin_page(void *handle, int number)
|
static void gtk_begin_page(drawing *dr, int number)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_begin_puzzle(void *handle, float xm, float xc,
|
static void gtk_begin_puzzle(drawing *dr, float xm, float xc,
|
||||||
float ym, float yc, int pw, int ph, float wmm)
|
float ym, float yc, int pw, int ph, float wmm)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
double ppw, pph, pox, poy, dpmmx, dpmmy;
|
double ppw, pph, pox, poy, dpmmx, dpmmy;
|
||||||
double scale;
|
double scale;
|
||||||
|
|
||||||
@ -1385,29 +1385,29 @@ static void gtk_begin_puzzle(void *handle, float xm, float xc,
|
|||||||
fe->hatchspace = 1.0 * pw / wmm;
|
fe->hatchspace = 1.0 * pw / wmm;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_end_puzzle(void *handle)
|
static void gtk_end_puzzle(drawing *dr)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
cairo_restore(fe->cr);
|
cairo_restore(fe->cr);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_end_page(void *handle, int number)
|
static void gtk_end_page(drawing *dr, int number)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_end_doc(void *handle)
|
static void gtk_end_doc(drawing *dr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_line_width(void *handle, float width)
|
static void gtk_line_width(drawing *dr, float width)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
cairo_set_line_width(fe->cr, width);
|
cairo_set_line_width(fe->cr, width);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void gtk_line_dotted(void *handle, bool dotted)
|
static void gtk_line_dotted(drawing *dr, bool dotted)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
|
|
||||||
if (dotted) {
|
if (dotted) {
|
||||||
const double dash = 35.0;
|
const double dash = 35.0;
|
||||||
@ -1435,6 +1435,7 @@ static const struct internal_drawing_api internal_printing = {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const struct drawing_api gtk_drawing = {
|
static const struct drawing_api gtk_drawing = {
|
||||||
|
1,
|
||||||
gtk_draw_text,
|
gtk_draw_text,
|
||||||
gtk_draw_rect,
|
gtk_draw_rect,
|
||||||
gtk_draw_line,
|
gtk_draw_line,
|
||||||
|
51
nestedvm.c
51
nestedvm.c
@ -54,59 +54,59 @@ void frontend_default_colour(frontend *fe, float *output)
|
|||||||
output[0] = output[1]= output[2] = 0.8f;
|
output[0] = output[1]= output[2] = 0.8f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nestedvm_status_bar(void *handle, const char *text)
|
void nestedvm_status_bar(drawing *dr, const char *text)
|
||||||
{
|
{
|
||||||
_call_java(4,0,(int)text,0);
|
_call_java(4,0,(int)text,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nestedvm_start_draw(void *handle)
|
void nestedvm_start_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
_call_java(5, 0, fe->w, fe->h);
|
_call_java(5, 0, fe->w, fe->h);
|
||||||
_call_java(4, 1, fe->ox, fe->oy);
|
_call_java(4, 1, fe->ox, fe->oy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nestedvm_clip(void *handle, int x, int y, int w, int h)
|
void nestedvm_clip(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
_call_java(5, w, h, 0);
|
_call_java(5, w, h, 0);
|
||||||
_call_java(4, 3, x + fe->ox, y + fe->oy);
|
_call_java(4, 3, x + fe->ox, y + fe->oy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nestedvm_unclip(void *handle)
|
void nestedvm_unclip(drawing *dr)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
_call_java(4, 4, fe->ox, fe->oy);
|
_call_java(4, 4, fe->ox, fe->oy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nestedvm_draw_text(void *handle, int x, int y, int fonttype, int fontsize,
|
void nestedvm_draw_text(drawing *dr, int x, int y, int fonttype, int fontsize,
|
||||||
int align, int colour, const char *text)
|
int align, int colour, const char *text)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
_call_java(5, x + fe->ox, y + fe->oy,
|
_call_java(5, x + fe->ox, y + fe->oy,
|
||||||
(fonttype == FONT_FIXED ? 0x10 : 0x0) | align);
|
(fonttype == FONT_FIXED ? 0x10 : 0x0) | align);
|
||||||
_call_java(7, fontsize, colour, (int)text);
|
_call_java(7, fontsize, colour, (int)text);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nestedvm_draw_rect(void *handle, int x, int y, int w, int h, int colour)
|
void nestedvm_draw_rect(drawing *dr, int x, int y, int w, int h, int colour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
_call_java(5, w, h, colour);
|
_call_java(5, w, h, colour);
|
||||||
_call_java(4, 5, x + fe->ox, y + fe->oy);
|
_call_java(4, 5, x + fe->ox, y + fe->oy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nestedvm_draw_line(void *handle, int x1, int y1, int x2, int y2,
|
void nestedvm_draw_line(drawing *dr, int x1, int y1, int x2, int y2,
|
||||||
int colour)
|
int colour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
_call_java(5, x2 + fe->ox, y2 + fe->oy, colour);
|
_call_java(5, x2 + fe->ox, y2 + fe->oy, colour);
|
||||||
_call_java(4, 6, x1 + fe->ox, y1 + fe->oy);
|
_call_java(4, 6, x1 + fe->ox, y1 + fe->oy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nestedvm_draw_poly(void *handle, int *coords, int npoints,
|
void nestedvm_draw_poly(drawing *dr, int *coords, int npoints,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
int i;
|
int i;
|
||||||
_call_java(4, 7, npoints, 0);
|
_call_java(4, 7, npoints, 0);
|
||||||
for (i = 0; i < npoints; i++) {
|
for (i = 0; i < npoints; i++) {
|
||||||
@ -115,10 +115,10 @@ void nestedvm_draw_poly(void *handle, int *coords, int npoints,
|
|||||||
_call_java(4, 8, outlinecolour, fillcolour);
|
_call_java(4, 8, outlinecolour, fillcolour);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nestedvm_draw_circle(void *handle, int cx, int cy, int radius,
|
void nestedvm_draw_circle(drawing *dr, int cx, int cy, int radius,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
_call_java(5, cx+fe->ox, cy+fe->oy, radius);
|
_call_java(5, cx+fe->ox, cy+fe->oy, radius);
|
||||||
_call_java(4, 9, outlinecolour, fillcolour);
|
_call_java(4, 9, outlinecolour, fillcolour);
|
||||||
}
|
}
|
||||||
@ -127,7 +127,7 @@ struct blitter {
|
|||||||
int handle, w, h, x, y;
|
int handle, w, h, x, y;
|
||||||
};
|
};
|
||||||
|
|
||||||
blitter *nestedvm_blitter_new(void *handle, int w, int h)
|
blitter *nestedvm_blitter_new(drawing *dr, int w, int h)
|
||||||
{
|
{
|
||||||
blitter *bl = snew(blitter);
|
blitter *bl = snew(blitter);
|
||||||
bl->handle = -1;
|
bl->handle = -1;
|
||||||
@ -136,16 +136,16 @@ blitter *nestedvm_blitter_new(void *handle, int w, int h)
|
|||||||
return bl;
|
return bl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nestedvm_blitter_free(void *handle, blitter *bl)
|
void nestedvm_blitter_free(drawing *dr, blitter *bl)
|
||||||
{
|
{
|
||||||
if (bl->handle != -1)
|
if (bl->handle != -1)
|
||||||
_call_java(4, 11, bl->handle, 0);
|
_call_java(4, 11, bl->handle, 0);
|
||||||
sfree(bl);
|
sfree(bl);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nestedvm_blitter_save(void *handle, blitter *bl, int x, int y)
|
void nestedvm_blitter_save(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
if (bl->handle == -1)
|
if (bl->handle == -1)
|
||||||
bl->handle = _call_java(4,10,bl->w, bl->h);
|
bl->handle = _call_java(4,10,bl->w, bl->h);
|
||||||
bl->x = x;
|
bl->x = x;
|
||||||
@ -153,9 +153,9 @@ void nestedvm_blitter_save(void *handle, blitter *bl, int x, int y)
|
|||||||
_call_java(8, bl->handle, x + fe->ox, y + fe->oy);
|
_call_java(8, bl->handle, x + fe->ox, y + fe->oy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nestedvm_blitter_load(void *handle, blitter *bl, int x, int y)
|
void nestedvm_blitter_load(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
assert(bl->handle != -1);
|
assert(bl->handle != -1);
|
||||||
if (x == BLITTER_FROMSAVED && y == BLITTER_FROMSAVED) {
|
if (x == BLITTER_FROMSAVED && y == BLITTER_FROMSAVED) {
|
||||||
x = bl->x;
|
x = bl->x;
|
||||||
@ -164,12 +164,12 @@ void nestedvm_blitter_load(void *handle, blitter *bl, int x, int y)
|
|||||||
_call_java(9, bl->handle, x + fe->ox, y + fe->oy);
|
_call_java(9, bl->handle, x + fe->ox, y + fe->oy);
|
||||||
}
|
}
|
||||||
|
|
||||||
void nestedvm_end_draw(void *handle)
|
void nestedvm_end_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
_call_java(4,2,0,0);
|
_call_java(4,2,0,0);
|
||||||
}
|
}
|
||||||
|
|
||||||
char *nestedvm_text_fallback(void *handle, const char *const *strings,
|
char *nestedvm_text_fallback(drawing *dr, const char *const *strings,
|
||||||
int nstrings)
|
int nstrings)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -180,6 +180,7 @@ char *nestedvm_text_fallback(void *handle, const char *const *strings,
|
|||||||
}
|
}
|
||||||
|
|
||||||
const struct drawing_api nestedvm_drawing = {
|
const struct drawing_api nestedvm_drawing = {
|
||||||
|
1,
|
||||||
nestedvm_draw_text,
|
nestedvm_draw_text,
|
||||||
nestedvm_draw_rect,
|
nestedvm_draw_rect,
|
||||||
nestedvm_draw_line,
|
nestedvm_draw_line,
|
||||||
|
1
nullfe.c
1
nullfe.c
@ -13,7 +13,6 @@ void get_random_seed(void **randseed, int *randseedsize)
|
|||||||
{ char *c = snewn(1, char); *c = 0; *randseed = c; *randseedsize = 1; }
|
{ char *c = snewn(1, char); *c = 0; *randseed = c; *randseedsize = 1; }
|
||||||
void deactivate_timer(frontend *fe) {}
|
void deactivate_timer(frontend *fe) {}
|
||||||
void activate_timer(frontend *fe) {}
|
void activate_timer(frontend *fe) {}
|
||||||
struct drawing { char dummy; };
|
|
||||||
drawing *drawing_new(const drawing_api *api, midend *me, void *handle)
|
drawing *drawing_new(const drawing_api *api, midend *me, void *handle)
|
||||||
{ return snew(drawing); }
|
{ return snew(drawing); }
|
||||||
void drawing_free(drawing *dr) { sfree(dr); }
|
void drawing_free(drawing *dr) { sfree(dr); }
|
||||||
|
63
osx.m
63
osx.m
@ -1507,10 +1507,10 @@ struct frontend {
|
|||||||
/*
|
/*
|
||||||
* Drawing routines called by the midend.
|
* Drawing routines called by the midend.
|
||||||
*/
|
*/
|
||||||
static void osx_draw_polygon(void *handle, const int *coords, int npoints,
|
static void osx_draw_polygon(drawing *dr, const int *coords, int npoints,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
NSBezierPath *path = [NSBezierPath bezierPath];
|
NSBezierPath *path = [NSBezierPath bezierPath];
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -1536,10 +1536,10 @@ static void osx_draw_polygon(void *handle, const int *coords, int npoints,
|
|||||||
[fe->colours[outlinecolour] set];
|
[fe->colours[outlinecolour] set];
|
||||||
[path stroke];
|
[path stroke];
|
||||||
}
|
}
|
||||||
static void osx_draw_circle(void *handle, int cx, int cy, int radius,
|
static void osx_draw_circle(drawing *dr, int cx, int cy, int radius,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
NSBezierPath *path = [NSBezierPath bezierPath];
|
NSBezierPath *path = [NSBezierPath bezierPath];
|
||||||
|
|
||||||
[[NSGraphicsContext currentContext] setShouldAntialias:YES];
|
[[NSGraphicsContext currentContext] setShouldAntialias:YES];
|
||||||
@ -1559,9 +1559,9 @@ static void osx_draw_circle(void *handle, int cx, int cy, int radius,
|
|||||||
[fe->colours[outlinecolour] set];
|
[fe->colours[outlinecolour] set];
|
||||||
[path stroke];
|
[path stroke];
|
||||||
}
|
}
|
||||||
static void osx_draw_line(void *handle, int x1, int y1, int x2, int y2, int colour)
|
static void osx_draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
NSBezierPath *path = [NSBezierPath bezierPath];
|
NSBezierPath *path = [NSBezierPath bezierPath];
|
||||||
NSPoint p1 = { x1 + 0.5, fe->h - y1 - 0.5 };
|
NSPoint p1 = { x1 + 0.5, fe->h - y1 - 0.5 };
|
||||||
NSPoint p2 = { x2 + 0.5, fe->h - y2 - 0.5 };
|
NSPoint p2 = { x2 + 0.5, fe->h - y2 - 0.5 };
|
||||||
@ -1579,12 +1579,12 @@ static void osx_draw_line(void *handle, int x1, int y1, int x2, int y2, int colo
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void osx_draw_thick_line(
|
static void osx_draw_thick_line(
|
||||||
void *handle, float thickness,
|
drawing *dr, float thickness,
|
||||||
float x1, float y1,
|
float x1, float y1,
|
||||||
float x2, float y2,
|
float x2, float y2,
|
||||||
int colour)
|
int colour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
NSBezierPath *path = [NSBezierPath bezierPath];
|
NSBezierPath *path = [NSBezierPath bezierPath];
|
||||||
|
|
||||||
assert(colour >= 0 && colour < fe->ncolours);
|
assert(colour >= 0 && colour < fe->ncolours);
|
||||||
@ -1597,9 +1597,9 @@ static void osx_draw_thick_line(
|
|||||||
[path stroke];
|
[path stroke];
|
||||||
}
|
}
|
||||||
|
|
||||||
static void osx_draw_rect(void *handle, int x, int y, int w, int h, int colour)
|
static void osx_draw_rect(drawing *dr, int x, int y, int w, int h, int colour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
NSRect r = { {x, fe->h - y - h}, {w,h} };
|
NSRect r = { {x, fe->h - y - h}, {w,h} };
|
||||||
|
|
||||||
[[NSGraphicsContext currentContext] setShouldAntialias:NO];
|
[[NSGraphicsContext currentContext] setShouldAntialias:NO];
|
||||||
@ -1609,11 +1609,11 @@ static void osx_draw_rect(void *handle, int x, int y, int w, int h, int colour)
|
|||||||
|
|
||||||
NSRectFill(r);
|
NSRectFill(r);
|
||||||
}
|
}
|
||||||
static void osx_draw_text(void *handle, int x, int y, int fonttype,
|
static void osx_draw_text(drawing *dr, int x, int y, int fonttype,
|
||||||
int fontsize, int align, int colour,
|
int fontsize, int align, int colour,
|
||||||
const char *text)
|
const char *text)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
NSString *string = [NSString stringWithUTF8String:text];
|
NSString *string = [NSString stringWithUTF8String:text];
|
||||||
NSDictionary *attr;
|
NSDictionary *attr;
|
||||||
NSFont *font;
|
NSFont *font;
|
||||||
@ -1646,7 +1646,7 @@ static void osx_draw_text(void *handle, int x, int y, int fonttype,
|
|||||||
|
|
||||||
[string drawAtPoint:point withAttributes:attr];
|
[string drawAtPoint:point withAttributes:attr];
|
||||||
}
|
}
|
||||||
static char *osx_text_fallback(void *handle, const char *const *strings,
|
static char *osx_text_fallback(drawing *dr, const char *const *strings,
|
||||||
int nstrings)
|
int nstrings)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -1660,7 +1660,7 @@ struct blitter {
|
|||||||
int x, y;
|
int x, y;
|
||||||
NSImage *img;
|
NSImage *img;
|
||||||
};
|
};
|
||||||
static blitter *osx_blitter_new(void *handle, int w, int h)
|
static blitter *osx_blitter_new(drawing *dr, int w, int h)
|
||||||
{
|
{
|
||||||
blitter *bl = snew(blitter);
|
blitter *bl = snew(blitter);
|
||||||
bl->x = bl->y = -1;
|
bl->x = bl->y = -1;
|
||||||
@ -1669,14 +1669,14 @@ static blitter *osx_blitter_new(void *handle, int w, int h)
|
|||||||
bl->img = [[NSImage alloc] initWithSize:NSMakeSize(w, h)];
|
bl->img = [[NSImage alloc] initWithSize:NSMakeSize(w, h)];
|
||||||
return bl;
|
return bl;
|
||||||
}
|
}
|
||||||
static void osx_blitter_free(void *handle, blitter *bl)
|
static void osx_blitter_free(drawing *dr, blitter *bl)
|
||||||
{
|
{
|
||||||
[bl->img release];
|
[bl->img release];
|
||||||
sfree(bl);
|
sfree(bl);
|
||||||
}
|
}
|
||||||
static void osx_blitter_save(void *handle, blitter *bl, int x, int y)
|
static void osx_blitter_save(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
int sx, sy, sX, sY, dx, dy, dX, dY;
|
int sx, sy, sX, sY, dx, dy, dX, dY;
|
||||||
[fe->image unlockFocus];
|
[fe->image unlockFocus];
|
||||||
[bl->img lockFocus];
|
[bl->img lockFocus];
|
||||||
@ -1718,9 +1718,9 @@ static void osx_blitter_save(void *handle, blitter *bl, int x, int y)
|
|||||||
bl->x = x;
|
bl->x = x;
|
||||||
bl->y = y;
|
bl->y = y;
|
||||||
}
|
}
|
||||||
static void osx_blitter_load(void *handle, blitter *bl, int x, int y)
|
static void osx_blitter_load(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
if (x == BLITTER_FROMSAVED && y == BLITTER_FROMSAVED) {
|
if (x == BLITTER_FROMSAVED && y == BLITTER_FROMSAVED) {
|
||||||
x = bl->x;
|
x = bl->x;
|
||||||
y = bl->y;
|
y = bl->y;
|
||||||
@ -1729,14 +1729,14 @@ static void osx_blitter_load(void *handle, blitter *bl, int x, int y)
|
|||||||
fromRect:NSMakeRect(0, 0, bl->w, bl->h)
|
fromRect:NSMakeRect(0, 0, bl->w, bl->h)
|
||||||
operation:NSCompositeCopy fraction:1.0];
|
operation:NSCompositeCopy fraction:1.0];
|
||||||
}
|
}
|
||||||
static void osx_draw_update(void *handle, int x, int y, int w, int h)
|
static void osx_draw_update(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
[fe->view setNeedsDisplayInRect:NSMakeRect(x, fe->h - y - h, w, h)];
|
[fe->view setNeedsDisplayInRect:NSMakeRect(x, fe->h - y - h, w, h)];
|
||||||
}
|
}
|
||||||
static void osx_clip(void *handle, int x, int y, int w, int h)
|
static void osx_clip(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
NSRect r = { {x, fe->h - y - h}, {w, h} };
|
NSRect r = { {x, fe->h - y - h}, {w, h} };
|
||||||
|
|
||||||
if (!fe->clipped)
|
if (!fe->clipped)
|
||||||
@ -1744,31 +1744,32 @@ static void osx_clip(void *handle, int x, int y, int w, int h)
|
|||||||
[NSBezierPath clipRect:r];
|
[NSBezierPath clipRect:r];
|
||||||
fe->clipped = true;
|
fe->clipped = true;
|
||||||
}
|
}
|
||||||
static void osx_unclip(void *handle)
|
static void osx_unclip(drawing *dr)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
if (fe->clipped)
|
if (fe->clipped)
|
||||||
[[NSGraphicsContext currentContext] restoreGraphicsState];
|
[[NSGraphicsContext currentContext] restoreGraphicsState];
|
||||||
fe->clipped = false;
|
fe->clipped = false;
|
||||||
}
|
}
|
||||||
static void osx_start_draw(void *handle)
|
static void osx_start_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
[fe->image lockFocus];
|
[fe->image lockFocus];
|
||||||
fe->clipped = false;
|
fe->clipped = false;
|
||||||
}
|
}
|
||||||
static void osx_end_draw(void *handle)
|
static void osx_end_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
[fe->image unlockFocus];
|
[fe->image unlockFocus];
|
||||||
}
|
}
|
||||||
static void osx_status_bar(void *handle, const char *text)
|
static void osx_status_bar(drawing *dr, const char *text)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
[fe->window setStatusLine:text];
|
[fe->window setStatusLine:text];
|
||||||
}
|
}
|
||||||
|
|
||||||
const struct drawing_api osx_drawing = {
|
const struct drawing_api osx_drawing = {
|
||||||
|
1,
|
||||||
osx_draw_text,
|
osx_draw_text,
|
||||||
osx_draw_rect,
|
osx_draw_rect,
|
||||||
osx_draw_line,
|
osx_draw_line,
|
||||||
|
65
ps.c
65
ps.c
@ -99,11 +99,11 @@ static void ps_stroke(psdata *ps, int colour)
|
|||||||
ps_setcolour_internal(ps, colour, " stroke");
|
ps_setcolour_internal(ps, colour, " stroke");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps_draw_text(void *handle, int x, int y, int fonttype,
|
static void ps_draw_text(drawing *dr, int x, int y, int fonttype,
|
||||||
int fontsize, int align, int colour,
|
int fontsize, int align, int colour,
|
||||||
const char *text)
|
const char *text)
|
||||||
{
|
{
|
||||||
psdata *ps = (psdata *)handle;
|
psdata *ps = GET_HANDLE_AS_TYPE(dr, psdata);
|
||||||
|
|
||||||
y = ps->ytop - y;
|
y = ps->ytop - y;
|
||||||
ps_setcolour(ps, colour);
|
ps_setcolour(ps, colour);
|
||||||
@ -133,9 +133,9 @@ static void ps_draw_text(void *handle, int x, int y, int fonttype,
|
|||||||
ps_printf(ps, "show\n");
|
ps_printf(ps, "show\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps_draw_rect(void *handle, int x, int y, int w, int h, int colour)
|
static void ps_draw_rect(drawing *dr, int x, int y, int w, int h, int colour)
|
||||||
{
|
{
|
||||||
psdata *ps = (psdata *)handle;
|
psdata *ps = GET_HANDLE_AS_TYPE(dr, psdata);
|
||||||
|
|
||||||
y = ps->ytop - y;
|
y = ps->ytop - y;
|
||||||
/*
|
/*
|
||||||
@ -146,10 +146,10 @@ static void ps_draw_rect(void *handle, int x, int y, int w, int h, int colour)
|
|||||||
ps_fill(ps, colour);
|
ps_fill(ps, colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps_draw_line(void *handle, int x1, int y1, int x2, int y2,
|
static void ps_draw_line(drawing *dr, int x1, int y1, int x2, int y2,
|
||||||
int colour)
|
int colour)
|
||||||
{
|
{
|
||||||
psdata *ps = (psdata *)handle;
|
psdata *ps = GET_HANDLE_AS_TYPE(dr, psdata);
|
||||||
|
|
||||||
y1 = ps->ytop - y1;
|
y1 = ps->ytop - y1;
|
||||||
y2 = ps->ytop - y2;
|
y2 = ps->ytop - y2;
|
||||||
@ -157,10 +157,10 @@ static void ps_draw_line(void *handle, int x1, int y1, int x2, int y2,
|
|||||||
ps_stroke(ps, colour);
|
ps_stroke(ps, colour);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps_draw_polygon(void *handle, const int *coords, int npoints,
|
static void ps_draw_polygon(drawing *dr, const int *coords, int npoints,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
psdata *ps = (psdata *)handle;
|
psdata *ps = GET_HANDLE_AS_TYPE(dr, psdata);
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -179,10 +179,10 @@ static void ps_draw_polygon(void *handle, const int *coords, int npoints,
|
|||||||
ps_stroke(ps, outlinecolour);
|
ps_stroke(ps, outlinecolour);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps_draw_circle(void *handle, int cx, int cy, int radius,
|
static void ps_draw_circle(drawing *dr, int cx, int cy, int radius,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
psdata *ps = (psdata *)handle;
|
psdata *ps = GET_HANDLE_AS_TYPE(dr, psdata);
|
||||||
|
|
||||||
cy = ps->ytop - cy;
|
cy = ps->ytop - cy;
|
||||||
|
|
||||||
@ -196,21 +196,21 @@ static void ps_draw_circle(void *handle, int cx, int cy, int radius,
|
|||||||
ps_stroke(ps, outlinecolour);
|
ps_stroke(ps, outlinecolour);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps_unclip(void *handle)
|
static void ps_unclip(drawing *dr)
|
||||||
{
|
{
|
||||||
psdata *ps = (psdata *)handle;
|
psdata *ps = GET_HANDLE_AS_TYPE(dr, psdata);
|
||||||
|
|
||||||
assert(ps->clipped);
|
assert(ps->clipped);
|
||||||
ps_printf(ps, "grestore\n");
|
ps_printf(ps, "grestore\n");
|
||||||
ps->clipped = false;
|
ps->clipped = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps_clip(void *handle, int x, int y, int w, int h)
|
static void ps_clip(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
psdata *ps = (psdata *)handle;
|
psdata *ps = GET_HANDLE_AS_TYPE(dr, psdata);
|
||||||
|
|
||||||
if (ps->clipped)
|
if (ps->clipped)
|
||||||
ps_unclip(ps);
|
ps_unclip(dr);
|
||||||
|
|
||||||
y = ps->ytop - y;
|
y = ps->ytop - y;
|
||||||
/*
|
/*
|
||||||
@ -223,16 +223,16 @@ static void ps_clip(void *handle, int x, int y, int w, int h)
|
|||||||
ps->clipped = true;
|
ps->clipped = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps_line_width(void *handle, float width)
|
static void ps_line_width(drawing *dr, float width)
|
||||||
{
|
{
|
||||||
psdata *ps = (psdata *)handle;
|
psdata *ps = GET_HANDLE_AS_TYPE(dr, psdata);
|
||||||
|
|
||||||
ps_printf(ps, "%g setlinewidth\n", width);
|
ps_printf(ps, "%g setlinewidth\n", width);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps_line_dotted(void *handle, bool dotted)
|
static void ps_line_dotted(drawing *dr, bool dotted)
|
||||||
{
|
{
|
||||||
psdata *ps = (psdata *)handle;
|
psdata *ps = GET_HANDLE_AS_TYPE(dr, psdata);
|
||||||
|
|
||||||
if (dotted) {
|
if (dotted) {
|
||||||
ps_printf(ps, "[ currentlinewidth 3 mul ] 0 setdash\n");
|
ps_printf(ps, "[ currentlinewidth 3 mul ] 0 setdash\n");
|
||||||
@ -241,7 +241,7 @@ static void ps_line_dotted(void *handle, bool dotted)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *ps_text_fallback(void *handle, const char *const *strings,
|
static char *ps_text_fallback(drawing *dr, const char *const *strings,
|
||||||
int nstrings)
|
int nstrings)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
@ -284,9 +284,9 @@ static char *ps_text_fallback(void *handle, const char *const *strings,
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps_begin_doc(void *handle, int pages)
|
static void ps_begin_doc(drawing *dr, int pages)
|
||||||
{
|
{
|
||||||
psdata *ps = (psdata *)handle;
|
psdata *ps = GET_HANDLE_AS_TYPE(dr, psdata);
|
||||||
|
|
||||||
fputs("%!PS-Adobe-3.0\n", ps->fp);
|
fputs("%!PS-Adobe-3.0\n", ps->fp);
|
||||||
fputs("%%Creator: Simon Tatham's Portable Puzzle Collection\n", ps->fp);
|
fputs("%%Creator: Simon Tatham's Portable Puzzle Collection\n", ps->fp);
|
||||||
@ -331,18 +331,18 @@ static void ps_begin_doc(void *handle, int pages)
|
|||||||
fputs("%%EndProlog\n", ps->fp);
|
fputs("%%EndProlog\n", ps->fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps_begin_page(void *handle, int number)
|
static void ps_begin_page(drawing *dr, int number)
|
||||||
{
|
{
|
||||||
psdata *ps = (psdata *)handle;
|
psdata *ps = GET_HANDLE_AS_TYPE(dr, psdata);
|
||||||
|
|
||||||
fprintf(ps->fp, "%%%%Page: %d %d\ngsave save\n%g dup scale\n",
|
fprintf(ps->fp, "%%%%Page: %d %d\ngsave save\n%g dup scale\n",
|
||||||
number, number, 72.0 / 25.4);
|
number, number, 72.0 / 25.4);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps_begin_puzzle(void *handle, float xm, float xc,
|
static void ps_begin_puzzle(drawing *dr, float xm, float xc,
|
||||||
float ym, float yc, int pw, int ph, float wmm)
|
float ym, float yc, int pw, int ph, float wmm)
|
||||||
{
|
{
|
||||||
psdata *ps = (psdata *)handle;
|
psdata *ps = GET_HANDLE_AS_TYPE(dr, psdata);
|
||||||
|
|
||||||
fprintf(ps->fp, "gsave\n"
|
fprintf(ps->fp, "gsave\n"
|
||||||
"clippath flattenpath pathbbox pop pop translate\n"
|
"clippath flattenpath pathbbox pop pop translate\n"
|
||||||
@ -358,28 +358,29 @@ static void ps_begin_puzzle(void *handle, float xm, float xc,
|
|||||||
ps->hatchspace = 1.0 * pw / wmm;
|
ps->hatchspace = 1.0 * pw / wmm;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps_end_puzzle(void *handle)
|
static void ps_end_puzzle(drawing *dr)
|
||||||
{
|
{
|
||||||
psdata *ps = (psdata *)handle;
|
psdata *ps = GET_HANDLE_AS_TYPE(dr, psdata);
|
||||||
|
|
||||||
fputs("grestore\n", ps->fp);
|
fputs("grestore\n", ps->fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps_end_page(void *handle, int number)
|
static void ps_end_page(drawing *dr, int number)
|
||||||
{
|
{
|
||||||
psdata *ps = (psdata *)handle;
|
psdata *ps = GET_HANDLE_AS_TYPE(dr, psdata);
|
||||||
|
|
||||||
fputs("restore grestore showpage\n", ps->fp);
|
fputs("restore grestore showpage\n", ps->fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ps_end_doc(void *handle)
|
static void ps_end_doc(drawing *dr)
|
||||||
{
|
{
|
||||||
psdata *ps = (psdata *)handle;
|
psdata *ps = GET_HANDLE_AS_TYPE(dr, psdata);
|
||||||
|
|
||||||
fputs("%%EOF\n", ps->fp);
|
fputs("%%EOF\n", ps->fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct drawing_api ps_drawing = {
|
static const struct drawing_api ps_drawing = {
|
||||||
|
1,
|
||||||
ps_draw_text,
|
ps_draw_text,
|
||||||
ps_draw_rect,
|
ps_draw_rect,
|
||||||
ps_draw_line,
|
ps_draw_line,
|
||||||
|
82
puzzles.h
82
puzzles.h
@ -755,43 +755,75 @@ struct game {
|
|||||||
int flags;
|
int flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define GET_HANDLE_AS_TYPE(dr, type) ((type*)((dr)->handle))
|
||||||
|
|
||||||
|
struct drawing {
|
||||||
|
const drawing_api *api;
|
||||||
|
void *handle;
|
||||||
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Data structure containing the drawing API implemented by the
|
* Data structure containing the drawing API implemented by the
|
||||||
* front end and also by cross-platform printing modules such as
|
* front end and also by cross-platform printing modules such as
|
||||||
* PostScript.
|
* PostScript.
|
||||||
*/
|
*/
|
||||||
struct drawing_api {
|
struct drawing_api {
|
||||||
void (*draw_text)(void *handle, int x, int y, int fonttype, int fontsize,
|
/*
|
||||||
|
* API version. Increment this when there is a breaking change to
|
||||||
|
* this API which requires front ends to change.
|
||||||
|
*
|
||||||
|
* There is expliclty not a public LATEST_API_VERSION define, so
|
||||||
|
* that front end authors will need to manually intervene when the
|
||||||
|
* version number changes. Naturally, this should be done
|
||||||
|
* sparingly.
|
||||||
|
*
|
||||||
|
* If a function is ever added to this API, please move this field
|
||||||
|
* to the _end_ of the structure, so that changes thereafter will
|
||||||
|
* shift the position of the version and lead to a compilation
|
||||||
|
* error if old implementations are not updated. Then remove this
|
||||||
|
* comment.
|
||||||
|
*
|
||||||
|
* The latest version number is 1.
|
||||||
|
*
|
||||||
|
* Change log:
|
||||||
|
*
|
||||||
|
* Version 1 (2024-08-14): Introduction of version number, in
|
||||||
|
* conjunction with changing every API function to take `drawing *`
|
||||||
|
* instead of `void *`.
|
||||||
|
*/
|
||||||
|
int version;
|
||||||
|
|
||||||
|
void (*draw_text)(drawing *dr, int x, int y, int fonttype, int fontsize,
|
||||||
int align, int colour, const char *text);
|
int align, int colour, const char *text);
|
||||||
void (*draw_rect)(void *handle, int x, int y, int w, int h, int colour);
|
void (*draw_rect)(drawing *dr, int x, int y, int w, int h, int colour);
|
||||||
void (*draw_line)(void *handle, int x1, int y1, int x2, int y2,
|
void (*draw_line)(drawing *dr, int x1, int y1, int x2, int y2,
|
||||||
int colour);
|
int colour);
|
||||||
void (*draw_polygon)(void *handle, const int *coords, int npoints,
|
void (*draw_polygon)(drawing *dr, const int *coords, int npoints,
|
||||||
int fillcolour, int outlinecolour);
|
int fillcolour, int outlinecolour);
|
||||||
void (*draw_circle)(void *handle, int cx, int cy, int radius,
|
void (*draw_circle)(drawing *dr, int cx, int cy, int radius,
|
||||||
int fillcolour, int outlinecolour);
|
int fillcolour, int outlinecolour);
|
||||||
void (*draw_update)(void *handle, int x, int y, int w, int h);
|
void (*draw_update)(drawing *dr, int x, int y, int w, int h);
|
||||||
void (*clip)(void *handle, int x, int y, int w, int h);
|
void (*clip)(drawing *dr, int x, int y, int w, int h);
|
||||||
void (*unclip)(void *handle);
|
void (*unclip)(drawing *dr);
|
||||||
void (*start_draw)(void *handle);
|
void (*start_draw)(drawing *dr);
|
||||||
void (*end_draw)(void *handle);
|
void (*end_draw)(drawing *dr);
|
||||||
void (*status_bar)(void *handle, const char *text);
|
void (*status_bar)(drawing *dr, const char *text);
|
||||||
blitter *(*blitter_new)(void *handle, int w, int h);
|
blitter *(*blitter_new)(drawing *dr, int w, int h);
|
||||||
void (*blitter_free)(void *handle, blitter *bl);
|
void (*blitter_free)(drawing *dr, blitter *bl);
|
||||||
void (*blitter_save)(void *handle, blitter *bl, int x, int y);
|
void (*blitter_save)(drawing *dr, blitter *bl, int x, int y);
|
||||||
void (*blitter_load)(void *handle, blitter *bl, int x, int y);
|
void (*blitter_load)(drawing *dr, blitter *bl, int x, int y);
|
||||||
void (*begin_doc)(void *handle, int pages);
|
void (*begin_doc)(drawing *dr, int pages);
|
||||||
void (*begin_page)(void *handle, int number);
|
void (*begin_page)(drawing *dr, int number);
|
||||||
void (*begin_puzzle)(void *handle, float xm, float xc,
|
void (*begin_puzzle)(drawing *dr, float xm, float xc,
|
||||||
float ym, float yc, int pw, int ph, float wmm);
|
float ym, float yc, int pw, int ph, float wmm);
|
||||||
void (*end_puzzle)(void *handle);
|
void (*end_puzzle)(drawing *dr);
|
||||||
void (*end_page)(void *handle, int number);
|
void (*end_page)(drawing *dr, int number);
|
||||||
void (*end_doc)(void *handle);
|
void (*end_doc)(drawing *dr);
|
||||||
void (*line_width)(void *handle, float width);
|
void (*line_width)(drawing *dr, float width);
|
||||||
void (*line_dotted)(void *handle, bool dotted);
|
void (*line_dotted)(drawing *dr, bool dotted);
|
||||||
char *(*text_fallback)(void *handle, const char *const *strings,
|
char *(*text_fallback)(drawing *dr, const char *const *strings,
|
||||||
int nstrings);
|
int nstrings);
|
||||||
void (*draw_thick_line)(void *handle, float thickness,
|
void (*draw_thick_line)(drawing *dr, float thickness,
|
||||||
float x1, float y1, float x2, float y2,
|
float x1, float y1, float x2, float y2,
|
||||||
int colour);
|
int colour);
|
||||||
};
|
};
|
||||||
|
89
windows.c
89
windows.c
@ -253,14 +253,14 @@ void get_random_seed(void **randseed, int *randseedsize)
|
|||||||
*randseedsize = sizeof(SYSTEMTIME);
|
*randseedsize = sizeof(SYSTEMTIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_status_bar(void *handle, const char *text)
|
static void win_status_bar(drawing *dr, const char *text)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
|
|
||||||
SetWindowText(fe->statusbar, text);
|
SetWindowText(fe->statusbar, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
static blitter *win_blitter_new(void *handle, int w, int h)
|
static blitter *win_blitter_new(drawing *dr, int w, int h)
|
||||||
{
|
{
|
||||||
blitter *bl = snew(blitter);
|
blitter *bl = snew(blitter);
|
||||||
|
|
||||||
@ -272,7 +272,7 @@ static blitter *win_blitter_new(void *handle, int w, int h)
|
|||||||
return bl;
|
return bl;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_blitter_free(void *handle, blitter *bl)
|
static void win_blitter_free(drawing *dr, blitter *bl)
|
||||||
{
|
{
|
||||||
if (bl->bitmap) DeleteObject(bl->bitmap);
|
if (bl->bitmap) DeleteObject(bl->bitmap);
|
||||||
sfree(bl);
|
sfree(bl);
|
||||||
@ -287,9 +287,9 @@ static void blitter_mkbitmap(frontend *fe, blitter *bl)
|
|||||||
|
|
||||||
/* BitBlt(dstDC, dstX, dstY, dstW, dstH, srcDC, srcX, srcY, dType) */
|
/* BitBlt(dstDC, dstX, dstY, dstW, dstH, srcDC, srcX, srcY, dType) */
|
||||||
|
|
||||||
static void win_blitter_save(void *handle, blitter *bl, int x, int y)
|
static void win_blitter_save(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
HDC hdc_win, hdc_blit;
|
HDC hdc_win, hdc_blit;
|
||||||
HBITMAP prev_blit;
|
HBITMAP prev_blit;
|
||||||
|
|
||||||
@ -316,9 +316,9 @@ static void win_blitter_save(void *handle, blitter *bl, int x, int y)
|
|||||||
ReleaseDC(fe->hwnd, hdc_win);
|
ReleaseDC(fe->hwnd, hdc_win);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_blitter_load(void *handle, blitter *bl, int x, int y)
|
static void win_blitter_load(drawing *dr, blitter *bl, int x, int y)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
HDC hdc_win, hdc_blit;
|
HDC hdc_win, hdc_blit;
|
||||||
HBITMAP prev_blit;
|
HBITMAP prev_blit;
|
||||||
|
|
||||||
@ -463,9 +463,9 @@ static void win_reset_pen(frontend *fe)
|
|||||||
DeleteObject(pen);
|
DeleteObject(pen);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_clip(void *handle, int x, int y, int w, int h)
|
static void win_clip(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
POINT p, q;
|
POINT p, q;
|
||||||
|
|
||||||
if (fe->drawstatus == NOTHING)
|
if (fe->drawstatus == NOTHING)
|
||||||
@ -476,9 +476,9 @@ static void win_clip(void *handle, int x, int y, int w, int h)
|
|||||||
IntersectClipRect(fe->hdc, p.x, p.y, q.x, q.y);
|
IntersectClipRect(fe->hdc, p.x, p.y, q.x, q.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_unclip(void *handle)
|
static void win_unclip(drawing *dr)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
|
|
||||||
if (fe->drawstatus == NOTHING)
|
if (fe->drawstatus == NOTHING)
|
||||||
return;
|
return;
|
||||||
@ -486,11 +486,11 @@ static void win_unclip(void *handle)
|
|||||||
SelectClipRgn(fe->hdc, NULL);
|
SelectClipRgn(fe->hdc, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_draw_text(void *handle, int x, int y, int fonttype,
|
static void win_draw_text(drawing *dr, int x, int y, int fonttype,
|
||||||
int fontsize, int align, int colour,
|
int fontsize, int align, int colour,
|
||||||
const char *text)
|
const char *text)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
POINT xy;
|
POINT xy;
|
||||||
int i;
|
int i;
|
||||||
LOGFONT lf;
|
LOGFONT lf;
|
||||||
@ -566,9 +566,9 @@ static void win_draw_text(void *handle, int x, int y, int fonttype,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_draw_rect(void *handle, int x, int y, int w, int h, int colour)
|
static void win_draw_rect(drawing *dr, int x, int y, int w, int h, int colour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
POINT p, q;
|
POINT p, q;
|
||||||
|
|
||||||
if (fe->drawstatus == NOTHING)
|
if (fe->drawstatus == NOTHING)
|
||||||
@ -593,9 +593,9 @@ static void win_draw_rect(void *handle, int x, int y, int w, int h, int colour)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_draw_line(void *handle, int x1, int y1, int x2, int y2, int colour)
|
static void win_draw_line(drawing *dr, int x1, int y1, int x2, int y2, int colour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
POINT pp[2];
|
POINT pp[2];
|
||||||
|
|
||||||
if (fe->drawstatus == NOTHING)
|
if (fe->drawstatus == NOTHING)
|
||||||
@ -610,10 +610,10 @@ static void win_draw_line(void *handle, int x1, int y1, int x2, int y2, int colo
|
|||||||
win_reset_pen(fe);
|
win_reset_pen(fe);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_draw_circle(void *handle, int cx, int cy, int radius,
|
static void win_draw_circle(drawing *dr, int cx, int cy, int radius,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
POINT p, q;
|
POINT p, q;
|
||||||
|
|
||||||
assert(outlinecolour >= 0);
|
assert(outlinecolour >= 0);
|
||||||
@ -634,10 +634,10 @@ static void win_draw_circle(void *handle, int cx, int cy, int radius,
|
|||||||
win_reset_pen(fe);
|
win_reset_pen(fe);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_draw_polygon(void *handle, const int *coords, int npoints,
|
static void win_draw_polygon(drawing *dr, const int *coords, int npoints,
|
||||||
int fillcolour, int outlinecolour)
|
int fillcolour, int outlinecolour)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
POINT *pts;
|
POINT *pts;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
@ -668,9 +668,9 @@ static void win_draw_polygon(void *handle, const int *coords, int npoints,
|
|||||||
sfree(pts);
|
sfree(pts);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_start_draw(void *handle)
|
static void win_start_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
HDC hdc_win;
|
HDC hdc_win;
|
||||||
|
|
||||||
assert(fe->drawstatus == NOTHING);
|
assert(fe->drawstatus == NOTHING);
|
||||||
@ -684,9 +684,9 @@ static void win_start_draw(void *handle)
|
|||||||
fe->drawstatus = DRAWING;
|
fe->drawstatus = DRAWING;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_draw_update(void *handle, int x, int y, int w, int h)
|
static void win_draw_update(drawing *dr, int x, int y, int w, int h)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
RECT r;
|
RECT r;
|
||||||
|
|
||||||
if (fe->drawstatus != DRAWING)
|
if (fe->drawstatus != DRAWING)
|
||||||
@ -701,9 +701,9 @@ static void win_draw_update(void *handle, int x, int y, int w, int h)
|
|||||||
InvalidateRect(fe->hwnd, &r, false);
|
InvalidateRect(fe->hwnd, &r, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_end_draw(void *handle)
|
static void win_end_draw(drawing *dr)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
assert(fe->drawstatus == DRAWING);
|
assert(fe->drawstatus == DRAWING);
|
||||||
SelectObject(fe->hdc, fe->prevbm);
|
SelectObject(fe->hdc, fe->prevbm);
|
||||||
DeleteDC(fe->hdc);
|
DeleteDC(fe->hdc);
|
||||||
@ -714,9 +714,9 @@ static void win_end_draw(void *handle)
|
|||||||
fe->drawstatus = NOTHING;
|
fe->drawstatus = NOTHING;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_line_width(void *handle, float width)
|
static void win_line_width(drawing *dr, float width)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
|
|
||||||
assert(fe->drawstatus != DRAWING);
|
assert(fe->drawstatus != DRAWING);
|
||||||
if (fe->drawstatus == NOTHING)
|
if (fe->drawstatus == NOTHING)
|
||||||
@ -725,9 +725,9 @@ static void win_line_width(void *handle, float width)
|
|||||||
fe->linewidth = (int)(width * fe->printpixelscale);
|
fe->linewidth = (int)(width * fe->printpixelscale);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_line_dotted(void *handle, bool dotted)
|
static void win_line_dotted(drawing *dr, bool dotted)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
|
|
||||||
assert(fe->drawstatus != DRAWING);
|
assert(fe->drawstatus != DRAWING);
|
||||||
if (fe->drawstatus == NOTHING)
|
if (fe->drawstatus == NOTHING)
|
||||||
@ -736,9 +736,9 @@ static void win_line_dotted(void *handle, bool dotted)
|
|||||||
fe->linedotted = dotted;
|
fe->linedotted = dotted;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_begin_doc(void *handle, int pages)
|
static void win_begin_doc(drawing *dr, int pages)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
|
|
||||||
assert(fe->drawstatus != DRAWING);
|
assert(fe->drawstatus != DRAWING);
|
||||||
if (fe->drawstatus == NOTHING)
|
if (fe->drawstatus == NOTHING)
|
||||||
@ -761,9 +761,9 @@ static void win_begin_doc(void *handle, int pages)
|
|||||||
fe->fontstart = fe->nfonts;
|
fe->fontstart = fe->nfonts;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_begin_page(void *handle, int number)
|
static void win_begin_page(drawing *dr, int number)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
|
|
||||||
assert(fe->drawstatus != DRAWING);
|
assert(fe->drawstatus != DRAWING);
|
||||||
if (fe->drawstatus == NOTHING)
|
if (fe->drawstatus == NOTHING)
|
||||||
@ -778,10 +778,10 @@ static void win_begin_page(void *handle, int number)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_begin_puzzle(void *handle, float xm, float xc,
|
static void win_begin_puzzle(drawing *dr, float xm, float xc,
|
||||||
float ym, float yc, int pw, int ph, float wmm)
|
float ym, float yc, int pw, int ph, float wmm)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
int ppw, pph, pox, poy;
|
int ppw, pph, pox, poy;
|
||||||
float mmpw, mmph, mmox, mmoy;
|
float mmpw, mmph, mmox, mmoy;
|
||||||
float scale;
|
float scale;
|
||||||
@ -829,14 +829,14 @@ static void win_begin_puzzle(void *handle, float xm, float xc,
|
|||||||
fe->linedotted = false;
|
fe->linedotted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_end_puzzle(void *handle)
|
static void win_end_puzzle(drawing *dr)
|
||||||
{
|
{
|
||||||
/* Nothing needs to be done here. */
|
/* Nothing needs to be done here. */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_end_page(void *handle, int number)
|
static void win_end_page(drawing *dr, int number)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
|
|
||||||
assert(fe->drawstatus != DRAWING);
|
assert(fe->drawstatus != DRAWING);
|
||||||
|
|
||||||
@ -852,9 +852,9 @@ static void win_end_page(void *handle, int number)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void win_end_doc(void *handle)
|
static void win_end_doc(drawing *dr)
|
||||||
{
|
{
|
||||||
frontend *fe = (frontend *)handle;
|
frontend *fe = GET_HANDLE_AS_TYPE(dr, frontend);
|
||||||
|
|
||||||
assert(fe->drawstatus != DRAWING);
|
assert(fe->drawstatus != DRAWING);
|
||||||
|
|
||||||
@ -885,7 +885,7 @@ static void win_end_doc(void *handle)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
char *win_text_fallback(void *handle, const char *const *strings, int nstrings)
|
char *win_text_fallback(drawing *dr, const char *const *strings, int nstrings)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* We assume Windows can cope with any UTF-8 likely to be
|
* We assume Windows can cope with any UTF-8 likely to be
|
||||||
@ -895,6 +895,7 @@ char *win_text_fallback(void *handle, const char *const *strings, int nstrings)
|
|||||||
}
|
}
|
||||||
|
|
||||||
const struct drawing_api win_drawing = {
|
const struct drawing_api win_drawing = {
|
||||||
|
1,
|
||||||
win_draw_text,
|
win_draw_text,
|
||||||
win_draw_rect,
|
win_draw_rect,
|
||||||
win_draw_line,
|
win_draw_line,
|
||||||
|
Reference in New Issue
Block a user