blob: a54d24465853cfd33ef44e7e491279087498383a [file] [log] [blame]
/*
* Twin - A Tiny Window System
* Copyright © 2004 Keith Packard <keithp@keithp.com>
* All rights reserved.
*
* This Library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This Library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with the Twin Library; see the file COPYING. If not,
* write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifndef _TWININT_H_
#define _TWININT_H_
#include "twin.h"
#include "twin_def.h"
#include <string.h>
/*
* Post-transformed points are stored in 12.4 fixed point
* values
*/
typedef int16_t twin_sfixed_t; /* 12.4 format */
typedef int32_t twin_dfixed_t; /* 24.8 format (12.4 * 12.4) */
#define twin_sfixed_floor(f) ((f) & ~0xf)
#define twin_sfixed_trunc(f) ((f) >> 4)
#define twin_sfixed_ceil(f) (((f) + 0xf) & ~0xf)
#define twin_sfixed_mod(f) ((f) & 0xf)
#define twin_int_to_sfixed(i) ((twin_sfixed_t) ((i) * 16))
#define twin_sfixed_to_fixed(s) (((twin_fixed_t) (s)) << 12)
#define twin_fixed_to_sfixed(f) ((twin_sfixed_t) ((f) >> 12))
#define twin_sfixed_to_dfixed(s) (((twin_dfixed_t) (s)) << 4)
/*
* 'double' is a no-no in any shipping code, but useful during
* development
*/
#define twin_double_to_sfixed(d) ((twin_sfixed_t) ((d) * 16.0))
#define twin_sfixed_to_double(f) ((double) (f) / 16.0)
#define TWIN_SFIXED_ONE (0x10)
#define TWIN_SFIXED_HALF (0x08)
#define TWIN_SFIXED_TOLERANCE (TWIN_SFIXED_ONE >> 2)
#define TWIN_SFIXED_MIN (-0x7fff)
#define TWIN_SFIXED_MAX (0x7fff)
/*
* Glyph coordinates are stored in 2.6 fixed point
*/
typedef signed char twin_gfixed_t;
#define TWIN_GFIXED_ONE (0x40)
/*
* Compositing stuff
*/
#define twin_int_mult(a,b,t) ((t) = (a) * (b) + 0x80, \
((((t)>>8 ) + (t))>>8 ))
#define twin_int_div(a,b) (((uint16_t) (a) * 255) / (b))
#define twin_get_8(v,i) ((uint16_t) (uint8_t) ((v) >> (i)))
#define twin_sat(t) ((uint8_t) ((t) | (0 - ((t) >> 8))))
#define twin_in(s,i,m,t) \
((twin_argb32_t) twin_int_mult (twin_get_8(s,i),(m),(t)) << (i))
#define twin_over(s,d,i,m,t) \
(((t) = twin_int_mult(twin_get_8(d,i),(m),(t)) + twin_get_8(s,i)),\
(twin_argb32_t) twin_sat (t) << (i))
#define twin_add(s,d,i,t) \
(((t) = twin_get_8(d,i) + twin_get_8(s,i)),\
(twin_argb32_t) twin_sat (t) << (i))
#define twin_argb32_to_rgb16(s) ((((s) >> 3) & 0x001f) | \
(((s) >> 5) & 0x07e0) | \
(((s) >> 8) & 0xf800))
#define twin_rgb16_to_argb32(s) \
(((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7)) | \
((((s) << 5) & 0xfc00) | (((s) >> 1) & 0x300)) | \
((((s) << 8) & 0xf80000) | (((s) << 3) & 0x70000)) | \
0xff000000)
typedef union {
twin_pointer_t p;
twin_argb32_t c;
} twin_source_u;
typedef void (*twin_src_msk_op) (twin_pointer_t dst,
twin_source_u src,
twin_source_u msk,
int width);
typedef void (*twin_src_op) (twin_pointer_t dst,
twin_source_u src,
int width);
typedef struct _twin_xform {
twin_pixmap_t *pixmap;
twin_pointer_t span;
twin_coord_t left;
twin_coord_t width;
twin_coord_t src_x;
twin_coord_t src_y;
} twin_xform_t;
/* twin_primitive.c */
typedef void twin_in_op_func (twin_pointer_t dst,
twin_source_u src,
twin_source_u msk,
int width);
typedef void twin_op_func (twin_pointer_t dst,
twin_source_u src,
int width);
/* Geometrical objects */
typedef struct _twin_spoint {
twin_sfixed_t x, y;
} twin_spoint_t;
struct _twin_path {
twin_spoint_t *points;
int size_points;
int npoints;
int *sublen;
int size_sublen;
int nsublen;
twin_state_t state;
};
typedef struct _twin_gpoint { twin_gfixed_t x, y; } twin_gpoint_t;
/*
* This needs to be refactored to reduce the number of functions...
*/
twin_in_op_func _twin_argb32_in_argb32_over_argb32;
twin_in_op_func _twin_argb32_in_rgb16_over_argb32;
twin_in_op_func _twin_argb32_in_a8_over_argb32;
twin_in_op_func _twin_argb32_in_c_over_argb32;
twin_in_op_func _twin_rgb16_in_argb32_over_argb32;
twin_in_op_func _twin_rgb16_in_rgb16_over_argb32;
twin_in_op_func _twin_rgb16_in_a8_over_argb32;
twin_in_op_func _twin_rgb16_in_c_over_argb32;
twin_in_op_func _twin_a8_in_argb32_over_argb32;
twin_in_op_func _twin_a8_in_rgb16_over_argb32;
twin_in_op_func _twin_a8_in_a8_over_argb32;
twin_in_op_func _twin_a8_in_c_over_argb32;
twin_in_op_func _twin_c_in_argb32_over_argb32;
twin_in_op_func _twin_c_in_rgb16_over_argb32;
twin_in_op_func _twin_c_in_a8_over_argb32;
twin_in_op_func _twin_c_in_c_over_argb32;
twin_in_op_func _twin_argb32_in_argb32_over_rgb16;
twin_in_op_func _twin_argb32_in_rgb16_over_rgb16;
twin_in_op_func _twin_argb32_in_a8_over_rgb16;
twin_in_op_func _twin_argb32_in_c_over_rgb16;
twin_in_op_func _twin_rgb16_in_argb32_over_rgb16;
twin_in_op_func _twin_rgb16_in_rgb16_over_rgb16;
twin_in_op_func _twin_rgb16_in_a8_over_rgb16;
twin_in_op_func _twin_rgb16_in_c_over_rgb16;
twin_in_op_func _twin_a8_in_argb32_over_rgb16;
twin_in_op_func _twin_a8_in_rgb16_over_rgb16;
twin_in_op_func _twin_a8_in_a8_over_rgb16;
twin_in_op_func _twin_a8_in_c_over_rgb16;
twin_in_op_func _twin_c_in_argb32_over_rgb16;
twin_in_op_func _twin_c_in_rgb16_over_rgb16;
twin_in_op_func _twin_c_in_a8_over_rgb16;
twin_in_op_func _twin_c_in_c_over_rgb16;
twin_in_op_func _twin_argb32_in_argb32_over_a8;
twin_in_op_func _twin_argb32_in_rgb16_over_a8;
twin_in_op_func _twin_argb32_in_a8_over_a8;
twin_in_op_func _twin_argb32_in_c_over_a8;
twin_in_op_func _twin_rgb16_in_argb32_over_a8;
twin_in_op_func _twin_rgb16_in_rgb16_over_a8;
twin_in_op_func _twin_rgb16_in_a8_over_a8;
twin_in_op_func _twin_rgb16_in_c_over_a8;
twin_in_op_func _twin_a8_in_argb32_over_a8;
twin_in_op_func _twin_a8_in_rgb16_over_a8;
twin_in_op_func _twin_a8_in_a8_over_a8;
twin_in_op_func _twin_a8_in_c_over_a8;
twin_in_op_func _twin_c_in_argb32_over_a8;
twin_in_op_func _twin_c_in_rgb16_over_a8;
twin_in_op_func _twin_c_in_a8_over_a8;
twin_in_op_func _twin_c_in_c_over_a8;
twin_in_op_func _twin_argb32_in_argb32_over_c;
twin_in_op_func _twin_argb32_in_argb32_source_argb32;
twin_in_op_func _twin_argb32_in_rgb16_source_argb32;
twin_in_op_func _twin_argb32_in_a8_source_argb32;
twin_in_op_func _twin_argb32_in_c_source_argb32;
twin_in_op_func _twin_rgb16_in_argb32_source_argb32;
twin_in_op_func _twin_rgb16_in_rgb16_source_argb32;
twin_in_op_func _twin_rgb16_in_a8_source_argb32;
twin_in_op_func _twin_rgb16_in_c_source_argb32;
twin_in_op_func _twin_a8_in_argb32_source_argb32;
twin_in_op_func _twin_a8_in_rgb16_source_argb32;
twin_in_op_func _twin_a8_in_a8_source_argb32;
twin_in_op_func _twin_a8_in_c_source_argb32;
twin_in_op_func _twin_c_in_argb32_source_argb32;
twin_in_op_func _twin_c_in_rgb16_source_argb32;
twin_in_op_func _twin_c_in_a8_source_argb32;
twin_in_op_func _twin_c_in_c_source_argb32;
twin_in_op_func _twin_argb32_in_argb32_source_rgb16;
twin_in_op_func _twin_argb32_in_rgb16_source_rgb16;
twin_in_op_func _twin_argb32_in_a8_source_rgb16;
twin_in_op_func _twin_argb32_in_c_source_rgb16;
twin_in_op_func _twin_rgb16_in_argb32_source_rgb16;
twin_in_op_func _twin_rgb16_in_rgb16_source_rgb16;
twin_in_op_func _twin_rgb16_in_a8_source_rgb16;
twin_in_op_func _twin_rgb16_in_c_source_rgb16;
twin_in_op_func _twin_a8_in_argb32_source_rgb16;
twin_in_op_func _twin_a8_in_rgb16_source_rgb16;
twin_in_op_func _twin_a8_in_a8_source_rgb16;
twin_in_op_func _twin_a8_in_c_source_rgb16;
twin_in_op_func _twin_c_in_argb32_source_rgb16;
twin_in_op_func _twin_c_in_rgb16_source_rgb16;
twin_in_op_func _twin_c_in_a8_source_rgb16;
twin_in_op_func _twin_c_in_c_source_rgb16;
twin_in_op_func _twin_argb32_in_argb32_source_a8;
twin_in_op_func _twin_argb32_in_rgb16_source_a8;
twin_in_op_func _twin_argb32_in_a8_source_a8;
twin_in_op_func _twin_argb32_in_c_source_a8;
twin_in_op_func _twin_rgb16_in_argb32_source_a8;
twin_in_op_func _twin_rgb16_in_rgb16_source_a8;
twin_in_op_func _twin_rgb16_in_a8_source_a8;
twin_in_op_func _twin_rgb16_in_c_source_a8;
twin_in_op_func _twin_a8_in_argb32_source_a8;
twin_in_op_func _twin_a8_in_rgb16_source_a8;
twin_in_op_func _twin_a8_in_a8_source_a8;
twin_in_op_func _twin_a8_in_c_source_a8;
twin_in_op_func _twin_c_in_argb32_source_a8;
twin_in_op_func _twin_c_in_rgb16_source_a8;
twin_in_op_func _twin_c_in_a8_source_a8;
twin_in_op_func _twin_c_in_c_source_a8;
twin_in_op_func _twin_argb32_in_argb32_source_c;
twin_op_func _twin_argb32_over_argb32;
twin_op_func _twin_rgb16_over_argb32;
twin_op_func _twin_a8_over_argb32;
twin_op_func _twin_c_over_argb32;
twin_op_func _twin_argb32_over_rgb16;
twin_op_func _twin_rgb16_over_rgb16;
twin_op_func _twin_a8_over_rgb16;
twin_op_func _twin_c_over_rgb16;
twin_op_func _twin_argb32_over_a8;
twin_op_func _twin_rgb16_over_a8;
twin_op_func _twin_a8_over_a8;
twin_op_func _twin_c_over_a8;
twin_op_func _twin_argb32_source_argb32;
twin_op_func _twin_rgb16_source_argb32;
twin_op_func _twin_a8_source_argb32;
twin_op_func _twin_c_source_argb32;
twin_op_func _twin_argb32_source_rgb16;
twin_op_func _twin_rgb16_source_rgb16;
twin_op_func _twin_a8_source_rgb16;
twin_op_func _twin_c_source_rgb16;
twin_op_func _twin_argb32_source_a8;
twin_op_func _twin_rgb16_source_a8;
twin_op_func _twin_a8_source_a8;
twin_op_func _twin_c_source_a8;
twin_op_func _twin_vec_argb32_over_argb32;
twin_op_func _twin_vec_argb32_source_argb32;
twin_argb32_t *
_twin_fetch_rgb16 (twin_pixmap_t *pixmap, int x, int y, int w, twin_argb32_t *span);
twin_argb32_t *
_twin_fetch_argb32 (twin_pixmap_t *pixmap, int x, int y, int w, twin_argb32_t *span);
/*
* Geometry helper functions
*/
twin_dfixed_t
_twin_distance_to_point_squared (twin_spoint_t *a, twin_spoint_t *b);
twin_dfixed_t
_twin_distance_to_line_squared (twin_spoint_t *p, twin_spoint_t *p1, twin_spoint_t *p2);
/*
* Polygon stuff
*/
/*
* Fixed point helper functions
*/
twin_sfixed_t
_twin_sfixed_sqrt (twin_sfixed_t as);
/*
* Matrix stuff
*/
twin_sfixed_t
_twin_matrix_x (twin_matrix_t *m, twin_fixed_t x, twin_fixed_t y);
twin_sfixed_t
_twin_matrix_y (twin_matrix_t *m, twin_fixed_t x, twin_fixed_t y);
twin_fixed_t
_twin_matrix_fx (twin_matrix_t *m, twin_fixed_t x, twin_fixed_t y);
twin_fixed_t
_twin_matrix_fy (twin_matrix_t *m, twin_fixed_t x, twin_fixed_t y);
twin_sfixed_t
_twin_matrix_dx (twin_matrix_t *m, twin_fixed_t dx, twin_fixed_t dy);
twin_sfixed_t
_twin_matrix_dy (twin_matrix_t *m, twin_fixed_t dx, twin_fixed_t dy);
twin_fixed_t
_twin_matrix_determinant (twin_matrix_t *matrix);
twin_sfixed_t
_twin_matrix_len (twin_matrix_t *m, twin_fixed_t dx, twin_fixed_t dy);
twin_point_t
_twin_matrix_expand (twin_matrix_t *matrix);
/*
* Path stuff
*/
/*
* A path
*/
twin_spoint_t
_twin_path_current_spoint (twin_path_t *path);
twin_spoint_t
_twin_path_subpath_first_spoint (twin_path_t *path);
void
_twin_path_smove (twin_path_t *path, twin_sfixed_t x, twin_sfixed_t y);
void
_twin_path_sdraw (twin_path_t *path, twin_sfixed_t x, twin_sfixed_t y);
void
_twin_path_scurve (twin_path_t *path,
twin_sfixed_t x1, twin_sfixed_t y1,
twin_sfixed_t x2, twin_sfixed_t y2,
twin_sfixed_t x3, twin_sfixed_t y3);
void
_twin_path_sfinish (twin_path_t *path);
/*
* Draw stuff
*/
void
_twin_draw_set_features(void);
/*
* Glyph stuff. Coordinates are stored in 2.6 fixed point format
*/
/*
* Check these whenever glyphs are changed
*/
#define TWIN_GLYPH_MAX_SNAP_X 4
#define TWIN_GLYPH_MAX_SNAP_Y 7
#define twin_glyph_left(g) ((g)[0])
#define twin_glyph_right(g) ((g)[1])
#define twin_glyph_ascent(g) ((g)[2])
#define twin_glyph_descent(g) ((g)[3])
#define twin_glyph_n_snap_x(g) ((g)[4])
#define twin_glyph_n_snap_y(g) ((g)[5])
#define twin_glyph_snap_x(g) (&g[6])
#define twin_glyph_snap_y(g) (twin_glyph_snap_x(g) + twin_glyph_n_snap_x(g))
/*
* dispatch stuff
*/
typedef struct _twin_queue {
struct _twin_queue *next;
struct _twin_queue *order;
twin_bool_t walking;
twin_bool_t deleted;
} twin_queue_t;
struct _twin_timeout {
twin_queue_t queue;
twin_time_t time;
twin_time_t delay;
twin_timeout_proc_t proc;
void *closure;
};
struct _twin_work {
twin_queue_t queue;
int priority;
twin_work_proc_t proc;
void *closure;
};
struct _twin_file {
twin_queue_t queue;
int file;
twin_file_op_t ops;
twin_file_proc_t proc;
void *closure;
};
typedef enum _twin_order {
TWIN_BEFORE = -1,
TWIN_AT = 0,
TWIN_AFTER = 1
} twin_order_t;
typedef twin_order_t (*twin_queue_proc_t) (twin_queue_t *a, twin_queue_t *b);
void
_twin_queue_insert (twin_queue_t **head,
twin_queue_proc_t proc,
twin_queue_t *new);
void
_twin_queue_remove (twin_queue_t **head,
twin_queue_t *old);
void
_twin_queue_reorder (twin_queue_t **head,
twin_queue_proc_t proc,
twin_queue_t *elem);
void
_twin_queue_delete (twin_queue_t **head,
twin_queue_t *old);
twin_queue_t *
_twin_queue_set_order (twin_queue_t **head);
void
_twin_queue_review_order (twin_queue_t *first);
void
_twin_run_file (twin_time_t delay);
void
_twin_run_timeout (void);
twin_time_t
_twin_timeout_delay (void);
void
_twin_run_work (void);
void
_twin_box_init (twin_box_t *box,
twin_box_t *parent,
twin_window_t *window,
twin_box_dir_t dir,
twin_dispatch_proc_t dispatch);
twin_dispatch_result_t
_twin_box_dispatch (twin_widget_t *widget, twin_event_t *event);
void
_twin_widget_init (twin_widget_t *widget,
twin_box_t *parent,
twin_window_t *window,
twin_widget_layout_t preferred,
twin_dispatch_proc_t dispatch);
void
_twin_widget_paint_shape (twin_widget_t *widget,
twin_shape_t shape,
twin_coord_t left,
twin_coord_t top,
twin_coord_t right,
twin_coord_t bottom,
twin_fixed_t radius);
twin_dispatch_result_t
_twin_widget_dispatch (twin_widget_t *widget, twin_event_t *event);
void
_twin_widget_queue_paint (twin_widget_t *widget);
void
_twin_widget_queue_layout (twin_widget_t *widget);
twin_bool_t
_twin_widget_contains (twin_widget_t *widget,
twin_coord_t x,
twin_coord_t y);
void
_twin_widget_bevel (twin_widget_t *widget,
twin_fixed_t bevel_width,
twin_bool_t down);
void
_twin_label_init (twin_label_t *label,
twin_box_t *parent,
const char *value,
twin_argb32_t foreground,
twin_fixed_t font_size,
twin_style_t font_style,
twin_dispatch_proc_t dispatch);
twin_dispatch_result_t
_twin_label_dispatch (twin_widget_t *widget, twin_event_t *event);
twin_dispatch_result_t
_twin_toplevel_dispatch (twin_widget_t *widget, twin_event_t *event);
void
_twin_toplevel_init (twin_toplevel_t *toplevel,
twin_dispatch_proc_t dispatch,
twin_window_t *window,
const char *name);
void
_twin_toplevel_queue_paint (twin_widget_t *widget);
void
_twin_toplevel_queue_layout (twin_widget_t *widget);
twin_dispatch_result_t
_twin_button_dispatch (twin_widget_t *widget, twin_event_t *event);
void
_twin_button_init (twin_button_t *button,
twin_box_t *parent,
const char *value,
twin_argb32_t foreground,
twin_fixed_t font_size,
twin_style_t font_style,
twin_dispatch_proc_t dispatch);
#endif /* _TWININT_H_ */