1 /* 
    2  * ctx is free software; you can redistribute it and/or
    3  * modify it under the terms of the GNU Lesser General Public
    4  * License as published by the Free Software Foundation; either
    5  * version 3 of the License, or (at your option) any later version.
    6  *
    7  * ctx is distributed in the hope that it will be useful,
    8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   10  * Lesser General Public License for more details.
   11  *
   12  * You should have received a copy of the GNU Lesser General Public
   13  * License along with ctx; if not, see <https://www.gnu.org/licenses/>.
   14  *
   15  * 2002, 2012, 2015, 2019, 2020 Øyvind Kolås <pippin@gimp.org>
   16  */
   17 
   18 #ifndef CTX_H
   19 #define CTX_H
   20 
   21 #ifdef __cplusplus
   22 extern "C" {
   23 #endif
   24 
   25 #include <stdint.h>
   26 #include <string.h>
   27 #include <stdio.h>
   28 
   29 typedef struct _Ctx            Ctx;
   30 typedef enum   _CtxPixelFormat CtxPixelFormat;
   31 typedef struct _CtxGlyph       CtxGlyph;
   32 
   33 /**
   34  * ctx_new:
   35  *
   36  * Create a new drawing context, this context has no pixels but
   37  * accumulates commands and can be played back on other ctx
   38  * render contexts.
   39  */
   40 Ctx *ctx_new (void);
   41 
   42 /**
   43  * ctx_new_for_framebuffer:
   44  *
   45  * Create a new drawing context for a framebuffer, rendering happens
   46  * immediately.
   47  */
   48 Ctx *ctx_new_for_framebuffer (void *data,
   49                               int width, int height, int stride,
   50                               CtxPixelFormat pixel_format);
   51 /**
   52  * ctx_new_ui:
   53  *
   54  * Create a new interactive ctx context, might depend on additional
   55  * integration.
   56  */
   57 Ctx *ctx_new_ui (int width, int height);
   58 
   59 /**
   60  * ctx_new_for_renderstream:
   61  *
   62  * Create a new drawing context for a pre-existing renderstream.
   63  */
   64 Ctx *ctx_new_for_renderstream (void *data, size_t length);
   65 void ctx_free                  (Ctx *ctx);
   66 
   67 
   68 /* clears and resets a context */
   69 void ctx_reset          (Ctx *ctx);
   70 
   71 void ctx_begin_path     (Ctx *ctx);
   72 void ctx_save           (Ctx *ctx);
   73 void ctx_restore        (Ctx *ctx);
   74 void ctx_start_group    (Ctx *ctx);
   75 void ctx_end_group      (Ctx *ctx);
   76 void ctx_clip           (Ctx *ctx);
   77 void ctx_identity       (Ctx *ctx);
   78 void ctx_rotate         (Ctx *ctx, float x);
   79 
   80 #define CTX_LINE_WIDTH_HAIRLINE -1000.0
   81 #define CTX_LINE_WIDTH_ALIASED  -1.0
   82 #define CTX_LINE_WIDTH_FAST     -1.0  /* aliased 1px wide line */
   83 void ctx_line_width       (Ctx *ctx, float x);
   84 void ctx_apply_transform  (Ctx *ctx, float a,  float b,  // hscale, hskew
   85                            float c,  float d,  // vskew,  vscale
   86                            float e,  float f); // htran,  vtran
   87 
   88 
   89 void  ctx_dirty_rect      (Ctx *ctx, int *x, int *y, int *width, int 
   90                            *height);
   91 
   92 void  ctx_font_size       (Ctx *ctx, float x);
   93 void  ctx_font            (Ctx *ctx, const char *font);
   94 void  ctx_scale           (Ctx *ctx, float x, float y);
   95 void  ctx_translate       (Ctx *ctx, float x, float y);
   96 void  ctx_line_to         (Ctx *ctx, float x, float y);
   97 void  ctx_move_to         (Ctx *ctx, float x, float y);
   98 void  ctx_curve_to        (Ctx *ctx, float cx0, float cy0,
   99                            float cx1, float cy1,
  100                            float x, float y);
  101 void  ctx_quad_to         (Ctx *ctx, float cx, float cy,
  102                            float x, float y);
  103 void  ctx_arc             (Ctx  *ctx,
  104                            float x, float y,
  105                            float radius,
  106                            float angle1, float angle2,
  107                            int   direction);
  108 void  ctx_arc_to          (Ctx *ctx, float x1, float y1,
  109                            float x2, float y2, float radius);
  110 void  ctx_rectangle       (Ctx *ctx,
  111                            float x0, float y0,
  112                            float w, float h);
  113 void  ctx_rel_line_to     (Ctx *ctx, float x, float y);
  114 void  ctx_rel_move_to     (Ctx *ctx, float x, float y);
  115 void  ctx_rel_curve_to    (Ctx *ctx,
  116                            float x0, float y0,
  117                            float x1, float y1,
  118                            float x2, float y2);
  119 void  ctx_rel_quad_to     (Ctx *ctx, float cx, float cy,
  120                            float x, float y);
  121 void  ctx_close_path      (Ctx *ctx);
  122 float ctx_get_font_size   (Ctx *ctx);
  123 float ctx_get_line_width  (Ctx *ctx);
  124 int   ctx_width           (Ctx *ctx);
  125 int   ctx_height          (Ctx *ctx);
  126 int   ctx_rev             (Ctx *ctx);
  127 float ctx_x               (Ctx *ctx);
  128 float ctx_y               (Ctx *ctx);
  129 void  ctx_current_point   (Ctx *ctx, float *x, float *y);
  130 void  ctx_get_transform   (Ctx *ctx, float *a, float *b,
  131                            float *c, float *d,
  132                            float *e, float *f);
  133 
  134 CtxGlyph *ctx_glyph_allocate (int n_glyphs);
  135 void      gtx_glyph_free     (CtxGlyph *glyphs);
  136 int  ctx_glyph            (Ctx *ctx, uint32_t unichar, int stroke);
  137 void ctx_arc              (Ctx  *ctx,
  138                            float x, float y,
  139                            float radius,
  140                            float angle1, float angle2,
  141                            int   direction);
  142 void ctx_arc_to           (Ctx *ctx, float x1, float y1,
  143                            float x2, float y2, float radius);
  144 
  145 void ctx_quad_to        (Ctx *ctx, float cx, float cy,
  146                          float x, float y);
  147 void ctx_arc            (Ctx  *ctx,
  148                          float x, float y,
  149                          float radius,
  150                          float angle1, float angle2,
  151                          int   direction);
  152 void ctx_arc_to         (Ctx *ctx, float x1, float y1,
  153                          float x2, float y2, float radius);
  154 
  155 void ctx_preserve       (Ctx *ctx);
  156 void ctx_fill           (Ctx *ctx);
  157 void ctx_stroke         (Ctx *ctx);
  158 void ctx_paint          (Ctx *ctx);
  159 
  160 void
  161 ctx_set_pixel_u8          (Ctx *ctx, uint16_t x, uint16_t y, uint8_t r, 
  162                            uint8_t g, uint8_t b, uint8_t a);
  163 
  164 void  ctx_global_alpha     (Ctx *ctx, float global_alpha);
  165 float ctx_get_global_alpha (Ctx *ctx);
  166 
  167 void ctx_rgba   (Ctx *ctx, float r, float g, float b, float a);
  168 void ctx_rgb    (Ctx *ctx, float r, float g, float b);
  169 void ctx_gray   (Ctx *ctx, float gray);
  170 void ctx_rgba8  (Ctx *ctx, uint8_t r, uint8_t g, uint8_t b, uint8_t a);
  171 void ctx_drgba  (Ctx *ctx, float r, float g, float b, float a);
  172 void ctx_cmyka  (Ctx *ctx, float c, float m, float y, float k, float a);
  173 void ctx_cmyk   (Ctx *ctx, float c, float m, float y, float k);
  174 void ctx_dcmyka (Ctx *ctx, float c, float m, float y, float k, float a);
  175 void ctx_dcmyk  (Ctx *ctx, float c, float m, float y, float k);
  176 
  177 /* there is also getters for colors, by first setting a color in one format 
  178 and getting
  179  * it with another color conversions can be done
  180  */
  181 
  182 void ctx_get_rgba   (Ctx *ctx, float *rgba);
  183 void ctx_get_graya  (Ctx *ctx, float *ya);
  184 void ctx_get_drgba  (Ctx *ctx, float *drgba);
  185 void ctx_get_cmyka  (Ctx *ctx, float *cmyka);
  186 void ctx_get_dcmyka (Ctx *ctx, float *dcmyka);
  187 int  ctx_in_fill    (Ctx *ctx, float x, float y);
  188 int  ctx_in_stroke  (Ctx *ctx, float x, float y);
  189 
  190 void ctx_linear_gradient (Ctx *ctx, float x0, float y0, float x1, float y1);
  191 void ctx_radial_gradient (Ctx *ctx, float x0, float y0, float r0,
  192                           float x1, float y1, float r1);
  193 /* XXX should be ctx_gradient_add_stop_rgba */
  194 void ctx_gradient_add_stop (Ctx *ctx, float pos, float r, float g, float b, 
  195                             float a);
  196 
  197 void ctx_gradient_add_stop_u8 (Ctx *ctx, float pos, uint8_t r, uint8_t g, 
  198                                uint8_t b, uint8_t a);
  199 
  200 /*ctx_texture_init:
  201  *
  202  * return value: the actual id assigned, if id is out of range - or later
  203  * when -1 as id will mean auto-assign.
  204  */
  205 int ctx_texture_init (Ctx *ctx, int id, int width, int height, int bpp,
  206                       uint8_t *pixels,
  207                       void (*freefunc) (void *pixels, void *user_data),
  208                       void *user_data);
  209 int ctx_texture_load        (Ctx *ctx, int id, const char *path);
  210 int ctx_texture_load_memory (Ctx *ctx, int id, const char *data, int length)
  211                              ;
  212 void ctx_texture_release    (Ctx *ctx, int id);
  213 void ctx_texture            (Ctx *ctx, int id, float x, float y);
  214 
  215 void ctx_image_path (Ctx *ctx, const char *path, float x, float y);
  216 
  217 typedef struct _CtxRenderstream CtxRenderstream;
  218 typedef void (*CtxFullCb) (CtxRenderstream *renderstream, void *data);
  219 
  220 void _ctx_set_store_clear (Ctx *ctx);
  221 void _ctx_set_transformation (Ctx *ctx, int transformation);
  222 
  223 Ctx *ctx_hasher_new (int width, int height, int cols, int rows);
  224 uint64_t ctx_hash_get_hash (Ctx *ctx, int col, int row);
  225 
  226 #ifdef _BABL_H
  227 #define CTX_BABL 1
  228 #else
  229 #define CTX_BABL 0
  230 #endif
  231 
  232 /* If cairo.h is included before ctx.h add cairo integration code
  233  */
  234 #ifdef CAIRO_H
  235 #define CTX_CAIRO 1
  236 #else
  237 #define CTX_CAIRO 0
  238 #endif
  239 
  240 #ifdef SDL_h_
  241 #define CTX_SDL 1
  242 #else
  243 #define CTX_SDL 0
  244 #endif
  245 
  246 #if CTX_SDL
  247 #define ctx_mutex_t            SDL_mutex
  248 #define ctx_create_mutex()     SDL_CreateMutex()
  249 #define ctx_lock_mutex(a)      SDL_LockMutex(a)
  250 #define ctx_unlock_mutex(a)    SDL_UnlockMutex(a)
  251 #else
  252 #define ctx_mutex_t           int
  253 #define ctx_create_mutex()    NULL
  254 #define ctx_lock_mutex(a)   
  255 #define ctx_unlock_mutex(a)  
  256 #endif
  257 
  258 
  259 #if CTX_CAIRO
  260 
  261 /* render the deferred commands of a ctx context to a cairo
  262  * context
  263  */
  264 void  ctx_render_cairo  (Ctx *ctx, cairo_t *cr);
  265 
  266 /* create a ctx context that directly renders to the specified
  267  * cairo context
  268  */
  269 Ctx * ctx_new_for_cairo (cairo_t *cr);
  270 #endif
  271 
  272 void ctx_render_stream  (Ctx *ctx, FILE *stream, int formatter);
  273 
  274 void ctx_render_ctx     (Ctx *ctx, Ctx *d_ctx);
  275 
  276 void ctx_start_move     (Ctx *ctx);
  277 
  278 
  279 int ctx_add_single      (Ctx *ctx, void *entry);
  280 
  281 uint32_t ctx_utf8_to_unichar (const char *input);
  282 int      ctx_unichar_to_utf8 (uint32_t  ch, uint8_t  *dest);
  283 
  284 /* The pixel formats supported as render targets
  285  */
  286 enum _CtxPixelFormat
  287 {
  288   CTX_FORMAT_GRAY8,
  289   CTX_FORMAT_GRAYA8,
  290   CTX_FORMAT_RGB8,
  291   CTX_FORMAT_RGBA8,
  292   CTX_FORMAT_BGRA8,
  293   CTX_FORMAT_RGB565,
  294   CTX_FORMAT_RGB565_BYTESWAPPED,
  295   CTX_FORMAT_RGB332,
  296   CTX_FORMAT_RGBAF,
  297   CTX_FORMAT_GRAYF,
  298   CTX_FORMAT_GRAYAF,
  299   CTX_FORMAT_GRAY1,
  300   CTX_FORMAT_GRAY2,
  301   CTX_FORMAT_GRAY4,
  302   CTX_FORMAT_CMYK8,
  303   CTX_FORMAT_CMYKA8,
  304   CTX_FORMAT_CMYKAF,
  305   CTX_FORMAT_DEVICEN1,
  306   CTX_FORMAT_DEVICEN2,
  307   CTX_FORMAT_DEVICEN3,
  308   CTX_FORMAT_DEVICEN4,
  309   CTX_FORMAT_DEVICEN5,
  310   CTX_FORMAT_DEVICEN6,
  311   CTX_FORMAT_DEVICEN7,
  312   CTX_FORMAT_DEVICEN8,
  313   CTX_FORMAT_DEVICEN9,
  314   CTX_FORMAT_DEVICEN10,
  315   CTX_FORMAT_DEVICEN11,
  316   CTX_FORMAT_DEVICEN12,
  317   CTX_FORMAT_DEVICEN13,
  318   CTX_FORMAT_DEVICEN14,
  319   CTX_FORMAT_DEVICEN15,
  320   CTX_FORMAT_DEVICEN16
  321 };
  322 
  323 typedef enum
  324 {
  325   CTX_FILL_RULE_EVEN_ODD,
  326   CTX_FILL_RULE_WINDING
  327 } CtxFillRule;
  328 
  329 typedef enum
  330 {
  331   CTX_COMPOSITE_SOURCE_OVER,
  332   CTX_COMPOSITE_COPY,
  333   CTX_COMPOSITE_SOURCE_IN,
  334   CTX_COMPOSITE_SOURCE_OUT,
  335   CTX_COMPOSITE_SOURCE_ATOP,
  336   CTX_COMPOSITE_CLEAR,
  337 
  338   CTX_COMPOSITE_DESTINATION_OVER,
  339   CTX_COMPOSITE_DESTINATION,
  340   CTX_COMPOSITE_DESTINATION_IN,
  341   CTX_COMPOSITE_DESTINATION_OUT,
  342   CTX_COMPOSITE_DESTINATION_ATOP,
  343   CTX_COMPOSITE_XOR,
  344 } CtxCompositingMode;
  345 
  346 typedef enum
  347 {
  348   CTX_BLEND_NORMAL,
  349   CTX_BLEND_MULTIPLY,
  350   CTX_BLEND_SCREEN,
  351   CTX_BLEND_OVERLAY,
  352   CTX_BLEND_DARKEN,
  353   CTX_BLEND_LIGHTEN,
  354   CTX_BLEND_COLOR_DODGE,
  355   CTX_BLEND_COLOR_BURN,
  356   CTX_BLEND_HARD_LIGHT,
  357   CTX_BLEND_SOFT_LIGHT,
  358   CTX_BLEND_DIFFERENCE,
  359   CTX_BLEND_EXCLUSION,
  360   CTX_BLEND_HUE, 
  361   CTX_BLEND_SATURATION, 
  362   CTX_BLEND_COLOR, 
  363   CTX_BLEND_LUMINOSITY,  // 15
  364   CTX_BLEND_DIVIDE,
  365   CTX_BLEND_ADDITION,
  366   CTX_BLEND_SUBTRACT,    // 18
  367 } CtxBlend;
  368 
  369 typedef enum
  370 {
  371   CTX_JOIN_BEVEL = 0,
  372   CTX_JOIN_ROUND = 1,
  373   CTX_JOIN_MITER = 2
  374 } CtxLineJoin;
  375 
  376 typedef enum
  377 {
  378   CTX_CAP_NONE   = 0,
  379   CTX_CAP_ROUND  = 1,
  380   CTX_CAP_SQUARE = 2
  381 } CtxLineCap;
  382 
  383 typedef enum
  384 {
  385   CTX_TEXT_BASELINE_ALPHABETIC = 0,
  386   CTX_TEXT_BASELINE_TOP,
  387   CTX_TEXT_BASELINE_HANGING,
  388   CTX_TEXT_BASELINE_MIDDLE,
  389   CTX_TEXT_BASELINE_IDEOGRAPHIC,
  390   CTX_TEXT_BASELINE_BOTTOM
  391 } CtxTextBaseline;
  392 
  393 typedef enum
  394 {
  395   CTX_TEXT_ALIGN_START = 0,
  396   CTX_TEXT_ALIGN_END,
  397   CTX_TEXT_ALIGN_CENTER,
  398   CTX_TEXT_ALIGN_LEFT,
  399   CTX_TEXT_ALIGN_RIGHT
  400 } CtxTextAlign;
  401 
  402 typedef enum
  403 {
  404   CTX_TEXT_DIRECTION_INHERIT = 0,
  405   CTX_TEXT_DIRECTION_LTR,
  406   CTX_TEXT_DIRECTION_RTL
  407 } CtxTextDirection;
  408 
  409 struct
  410 _CtxGlyph
  411 {
  412   uint32_t index;
  413   float    x;
  414   float    y;
  415 };
  416 
  417 void ctx_fill_rule            (Ctx *ctx, CtxFillRule fill_rule);
  418 void ctx_line_cap             (Ctx *ctx, CtxLineCap cap);
  419 void ctx_line_join            (Ctx *ctx, CtxLineJoin join);
  420 void ctx_compositing_mode     (Ctx *ctx, CtxCompositingMode mode);
  421 int  ctx_set_renderstream     (Ctx *ctx, void *data, int length);
  422 int  ctx_append_renderstream  (Ctx *ctx, void *data, int length);
  423 
  424 /* these are only needed for clients rendering text, as all text gets
  425  * converted to paths.
  426  */
  427 void  ctx_glyphs        (Ctx        *ctx,
  428                          CtxGlyph   *glyphs,
  429                          int         n_glyphs);
  430 
  431 void  ctx_glyphs_stroke (Ctx       *ctx,
  432                          CtxGlyph   *glyphs,
  433                          int         n_glyphs);
  434 
  435 void  ctx_text          (Ctx        *ctx,
  436                          const char *string);
  437 
  438 void  ctx_text_stroke   (Ctx        *ctx,
  439                          const char *string);
  440 
  441 /* returns the total horizontal advance if string had been rendered */
  442 float ctx_text_width    (Ctx        *ctx,
  443                          const char *string);
  444 
  445 float ctx_glyph_width   (Ctx *ctx, int unichar);
  446 
  447 int   ctx_load_font_ttf (const char *name, const void *ttf_contents, int 
  448                          length);
  449 
  450 typedef struct _CtxEntry CtxEntry;
  451 
  452 enum _CtxModifierState
  453 {
  454   CTX_MODIFIER_STATE_SHIFT   = (1<<0),
  455   CTX_MODIFIER_STATE_CONTROL = (1<<1),
  456   CTX_MODIFIER_STATE_ALT     = (1<<2),
  457   CTX_MODIFIER_STATE_BUTTON1 = (1<<3),
  458   CTX_MODIFIER_STATE_BUTTON2 = (1<<4),
  459   CTX_MODIFIER_STATE_BUTTON3 = (1<<5),
  460   CTX_MODIFIER_STATE_DRAG    = (1<<6), // pointer button is down (0 or any)
  461 };
  462 typedef enum _CtxModifierState CtxModifierState;
  463 
  464 enum _CtxScrollDirection
  465 {
  466   CTX_SCROLL_DIRECTION_UP,
  467   CTX_SCROLL_DIRECTION_DOWN,
  468   CTX_SCROLL_DIRECTION_LEFT,
  469   CTX_SCROLL_DIRECTION_RIGHT
  470 };
  471 typedef enum _CtxScrollDirection CtxScrollDirection;
  472 
  473 typedef struct _CtxEvent CtxEvent;
  474 
  475 void ctx_set_renderer (Ctx *ctx,
  476                        void *renderer);
  477 
  478 /* the following API is only available when CTX_EVENTS is defined to 1
  479  *
  480  * it provides the ability to register callbacks with the current path
  481  * that get delivered with transformed coordinates.
  482  */
  483 
  484 long     ctx_ticks (void);
  485 
  486 void _ctx_events_init     (Ctx *ctx);
  487 
  488 
  489 typedef void (*CtxCb) (CtxEvent *event,
  490                        void     *data,
  491                        void     *data2);
  492 typedef void (*CtxDestroyNotify) (void *data);
  493 
  494 enum _CtxEventType {
  495   CTX_PRESS          = 1 << 0,
  496   CTX_MOTION         = 1 << 1,
  497   CTX_RELEASE        = 1 << 2,
  498   CTX_ENTER          = 1 << 3,
  499   CTX_LEAVE          = 1 << 4,
  500   CTX_TAP            = 1 << 5,
  501   CTX_TAP_AND_HOLD   = 1 << 6,
  502 
  503   /* NYI: SWIPE, ZOOM ROT_ZOOM, */
  504 
  505   CTX_DRAG_PRESS     = 1 << 7,
  506   CTX_DRAG_MOTION    = 1 << 8,
  507   CTX_DRAG_RELEASE   = 1 << 9,
  508   CTX_KEY_DOWN       = 1 << 10,
  509   CTX_KEY_UP         = 1 << 11,
  510   CTX_SCROLL         = 1 << 12,
  511   CTX_MESSAGE        = 1 << 13,
  512   CTX_DROP           = 1 << 14,
  513 
  514   /* client should store state - preparing
  515                                  * for restart
  516                                  */
  517   CTX_POINTER  = (CTX_PRESS | CTX_MOTION | CTX_RELEASE | CTX_DROP),
  518   CTX_TAPS     = (CTX_TAP | CTX_TAP_AND_HOLD),
  519   CTX_CROSSING = (CTX_ENTER | CTX_LEAVE),
  520   CTX_DRAG     = (CTX_DRAG_PRESS | CTX_DRAG_MOTION | CTX_DRAG_RELEASE),
  521   CTX_KEY      = (CTX_KEY_DOWN | CTX_KEY_UP),
  522   CTX_MISC     = (CTX_MESSAGE),
  523   CTX_ANY      = (CTX_POINTER | CTX_DRAG | CTX_CROSSING | CTX_KEY | 
  524                  CTX_MISC | CTX_TAPS),
  525 };
  526 typedef enum _CtxEventType CtxEventType;
  527 
  528 #define CTX_CLICK   CTX_PRESS   // SHOULD HAVE MORE LOGIC
  529 
  530 struct _CtxEvent {
  531   CtxEventType  type;
  532   uint32_t time;
  533   Ctx     *ctx;
  534   int stop_propagate; /* when set - propagation is stopped */
  535 
  536   CtxModifierState state;
  537 
  538   int      device_no; /* 0 = left mouse button / virtual focus */
  539                       /* 1 = middle mouse button */
  540                       /* 2 = right mouse button */
  541                       /* 3 = first multi-touch .. (NYI) */
  542 
  543   float   device_x; /* untransformed (device) coordinates  */
  544   float   device_y;
  545 
  546   /* coordinates; and deltas for motion/drag events in user-coordinates: */
  547   float   x;
  548   float   y;
  549   float   start_x; /* start-coordinates (press) event for drag, */
  550   float   start_y; /*    untransformed coordinates */
  551   float   prev_x;  /* previous events coordinates */
  552   float   prev_y;
  553   float   delta_x; /* x - prev_x, redundant - but often useful */
  554   float   delta_y; /* y - prev_y, redundant - ..  */
  555 
  556 
  557   unsigned int unicode; /* only valid for key-events */
  558   const char *string;   /* as key can be "up" "down" "space" "backspace" 
  559   "a" "b" "ø" etc .. */
  560                         /* this is also where the message is delivered for
  561                          * MESSAGE events
  562                          *
  563                          * and the data for drop events are delivered
  564                          */
  565   CtxScrollDirection scroll_direction;
  566 
  567 
  568   // would be nice to add the bounding box of the hit-area causing
  569   // the event, making for instance scissored enter/leave repaint easier.
  570 };
  571 
  572 // layer-event "layer"  motion x y device_no 
  573 
  574 void ctx_add_key_binding_full (Ctx *ctx,
  575                                const char *key,
  576                                const char *action,
  577                                const char *label,
  578                                CtxCb       cb,
  579                                void       *cb_data,
  580                                CtxDestroyNotify destroy_notify,
  581                                void       *destroy_data);
  582 void ctx_add_key_binding (Ctx *ctx,
  583                           const char *key,
  584                           const char *action,
  585                           const char *label,
  586                           CtxCb cb,
  587                           void  *cb_data);
  588 typedef struct CtxBinding {
  589   char *nick;
  590   char *command;
  591   char *label;
  592   CtxCb cb;
  593   void *cb_data;
  594   CtxDestroyNotify destroy_notify;
  595   void  *destroy_data;
  596 } CtxBinding;
  597 CtxBinding *ctx_get_bindings (Ctx *ctx);
  598 void  ctx_clear_bindings     (Ctx *ctx);
  599 void  ctx_remove_idle        (Ctx *ctx, int handle);
  600 int   ctx_add_timeout_full   (Ctx *ctx, int ms, int (*idle_cb)(Ctx *ctx, 
  601                               void *idle_data), void *idle_data,
  602                               void (*destroy_notify)(void *destroy_data), 
  603                                     void *destroy_data);
  604 int   ctx_add_timeout        (Ctx *ctx, int ms, int (*idle_cb)(Ctx *ctx, 
  605                               void *idle_data), void *idle_data);
  606 int   ctx_add_idle_full      (Ctx *ctx, int (*idle_cb)(Ctx *ctx, void 
  607                               *idle_data), void *idle_data,
  608                               void (*destroy_notify)(void *destroy_data), 
  609                                     void *destroy_data);
  610 int   ctx_add_idle           (Ctx *ctx, int (*idle_cb)(Ctx *ctx, void 
  611                               *idle_data), void *idle_data);
  612 
  613 
  614 void ctx_add_hit_region (Ctx *ctx, const char *id);
  615 
  616 void ctx_listen_full (Ctx     *ctx,
  617                       float    x,
  618                       float    y,
  619                       float    width,
  620                       float    height,
  621                       CtxEventType  types,
  622                       CtxCb    cb,
  623                       void    *data1,
  624                       void    *data2,
  625                       void   (*finalize)(void *listen_data, void 
  626                               *listen_data2,
  627                                          void *finalize_data),
  628                       void    *finalize_data);
  629 void  ctx_event_stop_propagate (CtxEvent *event);
  630 void  ctx_listen               (Ctx          *ctx,
  631                                 CtxEventType  types,
  632                                 CtxCb         cb,
  633                                 void*         data1,
  634                                 void*         data2);
  635 
  636 int   ctx_pointer_is_down (Ctx *ctx, int no);
  637 float ctx_pointer_x (Ctx *ctx);
  638 float ctx_pointer_y (Ctx *ctx);
  639 void  ctx_freeze (Ctx *ctx);
  640 void  ctx_thaw   (Ctx *ctx);
  641 
  642 /* The following functions drive the event delivery, registered callbacks
  643  * are called in response to these being called.
  644  */
  645 
  646 int ctx_key_press (Ctx *ctx, unsigned int keyval,
  647                    const char *string, uint32_t time);
  648 int ctx_scrolled  (Ctx *ctx, float x, float y, CtxScrollDirection 
  649                    scroll_direction, uint32_t time);
  650 void ctx_incoming_message (Ctx *ctx, const char *message, long time);
  651 int ctx_pointer_motion    (Ctx *ctx, float x, float y, int device_no, 
  652                            uint32_t time);
  653 int ctx_pointer_release   (Ctx *ctx, float x, float y, int device_no, 
  654                            uint32_t time);
  655 int ctx_pointer_press     (Ctx *ctx, float x, float y, int device_no, 
  656                            uint32_t time);
  657 int ctx_pointer_drop      (Ctx *ctx, float x, float y, int device_no, 
  658                            uint32_t time,
  659                            char *string);
  660 
  661 ////////////////////
  662 
  663 typedef enum
  664 {
  665   // items marked with % are currently only for the parser
  666   // for instance for svg compatibility or simulated/converted color spaces
  667   // not the serialization/internal render stream
  668   //
  669   // unless specified, the arguments expected are 32bit float numbers.
  670   //
  671   CTX_FLUSH            = ';',
  672   CTX_ARC_TO           = 'A', // x1 y1 x2 y2 radius
  673   CTX_ARC              = 'B', // x y radius angle1 angle2 direction
  674   CTX_CURVE_TO         = 'C', // cx1 cy1 cx2 cy2 x y
  675 
  676   CTX_STROKE           = 'E', //
  677   CTX_FILL             = 'F', //
  678   CTX_RESTORE          = 'G', //
  679   CTX_HOR_LINE_TO      = 'H', // x
  680 
  681   CTX_ROTATE           = 'J', // radians
  682   CTX_COLOR            = 'K', // model, c1 c2 c3 ca - has a variable set of
  683   // arguments.
  684   CTX_LINE_TO          = 'L', // x y
  685   CTX_MOVE_TO          = 'M', // x y
  686   CTX_BEGIN_PATH       = 'N',
  687   CTX_SCALE            = 'O', // xscale yscale
  688   CTX_NEW_PAGE         = 'P', // - NYI
  689   CTX_QUAD_TO          = 'Q', // cx cy x y
  690   CTX_VIEW_BOX         = 'R', // x y width height
  691   CTX_SMOOTH_TO        = 'S', // cx cy x y
  692   CTX_SMOOTHQ_TO       = 'T', // x y
  693   CTX_RESET            = 'U', //
  694   CTX_VER_LINE_TO      = 'V', // y
  695   CTX_APPLY_TRANSFORM  = 'W', // a b c d e f - for set_transform combine 
  696                          with identity
  697   CTX_EXIT             = 'X', //
  698 
  699   CTX_CLOSE_PATH2      = 'Z', //
  700   CTX_REL_ARC_TO       = 'a', // x1 y1 x2 y2 radius
  701   CTX_CLIP             = 'b',
  702   CTX_REL_CURVE_TO     = 'c', // cx1 cy1 cx2 cy2 x y
  703 
  704   CTX_TRANSLATE        = 'e', // x y
  705   CTX_LINEAR_GRADIENT  = 'f', // x1 y1 x2 y2
  706   CTX_SAVE             = 'g',
  707   CTX_REL_HOR_LINE_TO  = 'h', // x
  708   CTX_TEXTURE          = 'i',
  709   CTX_PRESERVE         = 'j', // - make the following fill, stroke or clip 
  710                          leave the path
  711 
  712   CTX_SET_KEY          = 'k', // - used together with another char to 
  713                          identify a key to set
  714   CTX_REL_LINE_TO      = 'l', // x y
  715   CTX_REL_MOVE_TO      = 'm', // x y
  716   CTX_FONT         = 'n', // as used by text parser
  717   CTX_RADIAL_GRADIENT  = 'o', // x1 y1 radius1 x2 y2 radius2
  718   CTX_GRADIENT_STOP    = 'p', //   , count depends on current color model
  719   CTX_REL_QUAD_TO      = 'q', // cx cy x y
  720   CTX_RECTANGLE        = 'r', // x y width height
  721   CTX_REL_SMOOTH_TO    = 's', // cx cy x y
  722   CTX_REL_SMOOTHQ_TO   = 't', // x y
  723   CTX_TEXT_STROKE      = 'u', // string - utf8 string
  724   CTX_REL_VER_LINE_TO  = 'v', // y
  725   CTX_GLYPH            = 'w', // unichar fontsize
  726   CTX_TEXT             = 'x', // string | kern - utf8 data to shape or 
  727                          horizontal kerning amount
  728   CTX_IDENTITY         = 'y', //
  729   CTX_CLOSE_PATH       = 'z', //
  730 
  731   CTX_ROUND_RECTANGLE  = 'Y', // x y width height radius
  732   CTX_SET              = 'D', // key value - will take over k/K spots?
  733   CTX_GET              = 'd', // key -
  734   /* these commands have single byte binary representations,
  735    * but are two chars in text, values below 9 are used for
  736    * low integers of enum values. and can thus not be used here
  737    */
  738   CTX_SET_DRGB_SPACE       = 21, // hacks integer for now
  739   CTX_SET_RGB_SPACE        = 22, //
  740   CTX_SET_CMYK_SPACE       = 23, //
  741   CTX_SET_DCMYK_SPACE      = 24, //
  742 
  743   /* though expressed as two chars in serialization we have
  744    * dedicated byte commands for these setters
  745    */
  746   CTX_TEXT_ALIGN           = 17, // kt align - u8, default = 
  747                              CTX_TEXT_ALIGN_START
  748   CTX_TEXT_BASELINE        = 18, // kb baseline - u8, default = 
  749                              CTX_TEXT_ALIGN_ALPHABETIC
  750   CTX_TEXT_DIRECTION       = 19, // kd
  751   CTX_MITER_LIMIT          = 20, // km limit - float, default = 0.0
  752   CTX_GLOBAL_ALPHA         = 26, // ka alpha - default=1.0
  753   CTX_COMPOSITING_MODE     = 27, // kc mode - u8 , default=0
  754   CTX_BLEND_MODE           = '$',// kB mode - u8 , default=0
  755                                  // kb - text baseline
  756   CTX_FONT_SIZE            = 28, // kf size - float, default=?
  757   CTX_LINE_JOIN            = 29, // kj join - u8 , default=0
  758   CTX_LINE_CAP             = 30, // kc cap - u8, default = 0
  759   CTX_LINE_WIDTH           = 31, // kw width, default = 2.0
  760   CTX_FILL_RULE            = '!', // kr rule - u8, default = 
  761                              CTX_FILLE_RULE_EVEN_ODD
  762   CTX_SHADOW_BLUR          = '<', // ks
  763   CTX_SHADOW_COLOR         = '>', // kC
  764   CTX_SHADOW_OFFSET_X      = '?', // kx
  765   CTX_SHADOW_OFFSET_Y      = '&', // ky
  766   CTX_START_GROUP          = '{',
  767   CTX_END_GROUP            = '}',
  768 
  769   CTX_FUNCTION             = 25,
  770   //CTX_ENDFUN = 26,
  771 
  772   // non-alphabetic chars that get filtered out when parsing
  773   // are used for internal purposes
  774   //
  775   // unused:  . , : backslash  #  % ^ { } < > ? & /
  776   //           i 
  777   //
  778   CTX_CONT             = '\0', // - contains args from preceding entry
  779   CTX_SET_RGBA_U8      = '*', // r g b a - u8
  780   // NYI
  781   CTX_BITPIX           = 'I', // x, y, width, height, scale
  782   CTX_BITPIX_DATA      = 'j', //
  783 
  784   CTX_NOP              = ' ', //
  785   CTX_NEW_EDGE         = '+', // x0 y0 x1 y1 - s16
  786   CTX_EDGE             = '|', // x0 y0 x1 y1 - s16
  787   CTX_EDGE_FLIPPED     = '`', // x0 y0 x1 y1 - s16
  788 
  789   CTX_REPEAT_HISTORY   = ']', //
  790   CTX_DATA             = '(', // size size-in-entries - u32
  791   CTX_DATA_REV         = ')', // reverse traversal data marker
  792   // needed to be able to do backwards
  793   // traversal
  794   CTX_DEFINE_GLYPH     = '@', // unichar width - u32
  795   CTX_KERNING_PAIR     = '[', // glA glB kerning, glA and glB in u16 
  796                          kerning in s32
  797   CTX_SET_PIXEL        = '-', // r g b a x y - u8 for rgba, and u16 for x,y
  798 
  799   /* optimizations that reduce the number of entries used,
  800    * not visible outside the draw-stream compression -
  801    * these are using values that would mean numbers in an
  802    * SVG path.
  803    */
  804   CTX_REL_LINE_TO_X4            = '0', // x1 y1 x2 y2 x3 y3 x4 y4   -- s8
  805   CTX_REL_LINE_TO_REL_CURVE_TO  = '1', // x1 y1 cx1 cy1 cx2 cy2 x y -- s8
  806   CTX_REL_CURVE_TO_REL_LINE_TO  = '2', // cx1 cy1 cx2 cy2 x y x1 y1 -- s8
  807   CTX_REL_CURVE_TO_REL_MOVE_TO  = '3', // cx1 cy1 cx2 cy2 x y x1 y1 -- s8
  808   CTX_REL_LINE_TO_X2            = '4', // x1 y1 x2 y2 -- s16
  809   CTX_MOVE_TO_REL_LINE_TO       = '5', // x1 y1 x2 y2 -- s16
  810   CTX_REL_LINE_TO_REL_MOVE_TO   = '6', // x1 y1 x2 y2 -- s16
  811   CTX_FILL_MOVE_TO              = '7', // x y
  812   CTX_REL_QUAD_TO_REL_QUAD_TO   = '8', // cx1 x1 cy1 y1 cx1 x2 cy1 y1 -- s8
  813   CTX_REL_QUAD_TO_S16           = '9', // cx1 cy1 x y                 - s16
  814 } CtxCode;
  815 
  816 /* we only care about the tight packing for this specific
  817  * structx as we do indexing across members in arrays of it,
  818  * to make sure its size becomes 9bytes -
  819  * the pack pragma is also sufficient on recent gcc versions
  820  */
  821 #pragma pack(push,1)
  822 struct
  823   _CtxEntry
  824 {
  825   uint8_t code;
  826   union
  827   {
  828     float    f[2];
  829     uint8_t  u8[8];
  830     int8_t   s8[8];
  831     uint16_t u16[4];
  832     int16_t  s16[4];
  833     uint32_t u32[2];
  834     int32_t  s32[2];
  835     uint64_t u64[1]; // unused
  836   } data; // 9bytes long, we're favoring compactness and correctness
  837   // over performance. By sacrificing float precision, zeroing
  838   // first 8bit of f[0] would permit 8bytes long and better
  839   // aglinment and cacheline behavior.
  840 };
  841 typedef struct _CtxCommand CtxCommand;
  842 typedef struct _CtxIterator CtxIterator;
  843 
  844 CtxIterator *
  845 ctx_current_path (Ctx *ctx);
  846 void
  847 ctx_path_extents (Ctx *ctx, float *ex1, float *ey1, float *ex2, float *ey2);
  848 
  849 
  850 /* definitions that determine which features are included and their 
  851 settings,
  852  * for particular platforms - in particular microcontrollers ctx might need
  853  * tuning for different quality/performance/resource constraints.
  854  *
  855  * the way to configure ctx is to set these defines, before both including 
  856  it
  857  * as a header and in the file where CTX_IMPLEMENTATION is set to include 
  858  the
  859  * implementation for different featureset and runtime settings.
  860  *
  861  */
  862 
  863 #ifndef CTX_RASTERIZER  // set to 0 before to disable rasterizer code, 
  864 useful for clients that only
  865 // build journals.
  866 #define CTX_RASTERIZER   1
  867 #endif
  868 
  869 /* whether the font rendering happens in backend or front-end of API,
  870  * the option exists for generating ctx fonts.
  871  */
  872 #ifndef CTX_BACKEND_TEXT
  873 #define CTX_BACKEND_TEXT 1
  874 #endif
  875 
  876 
  877 
  878 /* force full antialising */
  879 #ifndef CTX_RASTERIZER_FORCE_AA
  880 #define CTX_RASTERIZER_FORCE_AA  0
  881 #endif
  882 
  883 /* when AA is not forced, the slope below which full AA get enabled.
  884  */
  885 
  886 
  887 #define CTX_RASTERIZER_AA_SLOPE_LIMIT    (2125/CTX_SUBDIV/rasterizer->aa)
  888 
  889 #ifndef CTX_RASTERIZER_AA_SLOPE_DEBUG
  890 #define CTX_RASTERIZER_AA_SLOPE_DEBUG 0
  891 #endif
  892 
  893 
  894 /* subpixel-aa coordinates used in BITPACKing of renderstream
  895  */
  896 #define CTX_SUBDIV   4 // higher gives higher quality, but 4096wide 
  897 rendering
  898                        // stops working
  899 
  900 // 8    12 68 40 24
  901 // 16   12 68 40 24
  902 /* scale-factor for font outlines prior to bit quantization by CTX_SUBDIV
  903  *
  904  * changing this also changes font file format
  905  */
  906 #define CTX_BAKE_FONT_SIZE    160
  907 
  908 /* pack some linetos/curvetos/movetos into denser renderstream 
  909 indstructions,
  910  * permitting more vectors to be stored in the same space.
  911  */
  912 #ifndef CTX_BITPACK
  913 #define CTX_BITPACK           1
  914 #endif
  915 
  916 /* whether we have a shape-cache where we keep pre-rasterized bitmaps of 
  917 commonly
  918  * occuring small shapes.
  919  */
  920 #ifndef CTX_SHAPE_CACHE
  921 #define CTX_SHAPE_CACHE       0
  922 #endif
  923 
  924 /* size (in pixels, w*h) that we cache rasterization for
  925  */
  926 #ifndef CTX_SHAPE_CACHE_DIM
  927 #define CTX_SHAPE_CACHE_DIM      (16*16)
  928 #endif
  929 
  930 #ifndef CTX_SHAPE_CACHE_MAX_DIM
  931 #define CTX_SHAPE_CACHE_MAX_DIM  32
  932 #endif
  933 
  934 #ifndef CTX_PARSER_MAXLEN
  935 #define CTX_PARSER_MAXLEN  1024 // this is the largest text string we 
  936 support
  937 #endif
  938 
  939 #ifndef CTX_COMPOSITING_GROUPS
  940 #define CTX_COMPOSITING_GROUPS   1
  941 #endif
  942 
  943 /* maximum nesting level of compositing groups
  944  */
  945 #ifndef CTX_GROUP_MAX
  946 #define CTX_GROUP_MAX     8
  947 #endif
  948 
  949 #ifndef CTX_ENABLE_CLIP
  950 #define CTX_ENABLE_CLIP   1
  951 #endif
  952 
  953 /* use a 1bit clip buffer, saving RAM on microcontrollers, other rendering
  954  * will still be antialiased.
  955  */
  956 #ifndef CTX_1BIT_CLIP
  957 #define CTX_1BIT_CLIP 0
  958 #endif
  959 
  960 /* maximum number of entries in shape cache
  961  */
  962 #ifndef CTX_SHAPE_CACHE_ENTRIES
  963 #define CTX_SHAPE_CACHE_ENTRIES  160
  964 #endif
  965 
  966 #ifndef CTX_ENABLE_SHADOW_BLUR
  967 #define CTX_ENABLE_SHADOW_BLUR    1
  968 #endif
  969 
  970 #ifndef CTX_GRADIENTS
  971 #define CTX_GRADIENTS      1
  972 #endif
  973 
  974 /* some optinal micro-optimizations that are known to increase code size
  975  */
  976 #ifndef CTX_BLOATY_FAST_PATHS
  977 #define CTX_BLOATY_FAST_PATHS 1
  978 #endif
  979 
  980 #ifndef CTX_GRADIENT_CACHE
  981 #define CTX_GRADIENT_CACHE 1
  982 #endif
  983 
  984 #ifndef CTX_FONTS_FROM_FILE
  985 #define CTX_FONTS_FROM_FILE 1
  986 #endif
  987 
  988 #ifndef CTX_FORMATTER
  989 #define CTX_FORMATTER 1
  990 #endif
  991 
  992 #ifndef CTX_PARSER
  993 #define CTX_PARSER 1
  994 #endif
  995 
  996 #ifndef CTX_CURRENT_PATH
  997 #define CTX_CURRENT_PATH 1
  998 #endif
  999 
 1000 #ifndef CTX_XML
 1001 #define CTX_XML 1
 1002 #endif
 1003 
 1004 /* when ctx_math is defined, which it is by default, we use ctx' own
 1005  * implementations of math functions, instead of relying on math.h
 1006  * the possible inlining gives us a slight speed-gain, and on
 1007  * embedded platforms guarantees that we do not do double precision
 1008  * math.
 1009  */
 1010 #ifndef CTX_MATH
 1011 #define CTX_MATH           1  // use internal fast math for sqrt,sin,cos,
 1012 atan2f etc.
 1013 #endif
 1014 
 1015 #define ctx_log(fmt, ...)
 1016 //#define ctx_log(str, a...) fprintf(stderr, str, ##a)
 1017 
 1018 /* the initial journal size - for both rasterizer
 1019  * edgelist and renderstram.
 1020  */
 1021 #ifndef CTX_MIN_JOURNAL_SIZE
 1022 #define CTX_MIN_JOURNAL_SIZE   1024*10
 1023 #endif
 1024 
 1025 /* The maximum size we permit the renderstream to grow to,
 1026  * the memory used is this number * 9, where 9 is sizeof(CtxEntry)
 1027  */
 1028 #ifndef CTX_MAX_JOURNAL_SIZE
 1029 #define CTX_MAX_JOURNAL_SIZE   1024*10
 1030 #endif
 1031 
 1032 #ifndef CTX_RENDERSTREAM_STATIC
 1033 #define CTX_RENDERSTREAM_STATIC 0
 1034 #endif
 1035 
 1036 #ifndef CTX_MIN_EDGE_LIST_SIZE
 1037 #define CTX_MIN_EDGE_LIST_SIZE   128
 1038 #endif
 1039 
 1040 /* The maximum size we permit the renderstream to grow to
 1041  */
 1042 #ifndef CTX_MAX_EDGE_LIST_SIZE
 1043 #define CTX_MAX_EDGE_LIST_SIZE   4096
 1044 #endif
 1045 
 1046 //#define CTX_STRINGPOOL_SIZE   6000 // needed for tiger
 1047 //#define CTX_STRINGPOOL_SIZE   8000 // needed for debian logo in bw
 1048 #define CTX_STRINGPOOL_SIZE   8500 // needed for debian logo in color
 1049 
 1050 /* whether we dither or not for gradients
 1051  */
 1052 #ifndef CTX_DITHER
 1053 #define CTX_DITHER 1
 1054 #endif
 1055 
 1056 /*  only source-over clear and copy will work, the API still
 1057  *  through - but the renderer is limited, for use to measure
 1058  *  size and possibly in severely constrained ROMs.
 1059  */
 1060 #ifndef CTX_BLENDING_AND_COMPOSITING
 1061 #define CTX_BLENDING_AND_COMPOSITING 1
 1062 #endif
 1063 
 1064 /*  this forces the inlining of some performance
 1065  *  critical paths.
 1066  */
 1067 #ifndef CTX_FORCE_INLINES
 1068 #define CTX_FORCE_INLINES       1
 1069 #endif
 1070 
 1071 /* this enables alternate syntax in parsing, like _ instead of camel case,
 1072  * surprisingly permitting some aliases does not increase the size of the
 1073  * generated parser.
 1074  */
 1075 #ifndef  CTX_POSTEL_PRINCIPLED_INPUT
 1076 #define CTX_POSTEL_PRINCIPLED_INPUT     0
 1077 #endif
 1078 
 1079 /* create one-off inlined inner loop for normal blend mode
 1080  */
 1081 #ifndef CTX_INLINED_NORMAL     
 1082 #define CTX_INLINED_NORMAL      1
 1083 #endif
 1084 
 1085 #ifndef CTX_INLINED_GRADIENTS
 1086 #define CTX_INLINED_GRADIENTS   1
 1087 #endif
 1088 
 1089 #ifndef CTX_BRAILLE_TEXT
 1090 #define CTX_BRAILLE_TEXT        0
 1091 #endif
 1092 
 1093 #ifndef CTX_AVX2
 1094 #ifdef _IMMINTRIN_H_INCLUDED
 1095 #define CTX_AVX2         1
 1096 #else
 1097 #define CTX_AVX2         0
 1098 #endif
 1099 #endif
 1100 
 1101 /* do 
 1102  */
 1103 #ifndef CTX_NATIVE_GRAYA8
 1104 #define CTX_NATIVE_GRAYA8       0
 1105 #endif
 1106 
 1107 #ifndef CTX_ENABLE_CMYK
 1108 #define CTX_ENABLE_CMYK         1
 1109 #endif
 1110 
 1111 #ifndef CTX_ENABLE_CM
 1112 #define CTX_ENABLE_CM           1
 1113 #endif
 1114 
 1115 #ifndef CTX_RENDER_CTX
 1116 #define CTX_RENDER_CTX          1
 1117 #endif
 1118 
 1119 #ifndef CTX_EVENTS
 1120 #define CTX_EVENTS              1
 1121 #endif
 1122 
 1123 #ifndef CTX_LIMIT_FORMATS
 1124 #define CTX_LIMIT_FORMATS       0
 1125 #endif
 1126 
 1127 /* by default ctx includes all pixel formats, on microcontrollers
 1128  * it can be useful to slim down code and runtime size by only
 1129  * defining the used formats, set CTX_LIMIT_FORMATS to 1, and
 1130  * manually add CTX_ENABLE_ flags for each of them.
 1131  */
 1132 #if CTX_LIMIT_FORMATS
 1133 #else
 1134 
 1135 #define CTX_ENABLE_GRAY1                1
 1136 #define CTX_ENABLE_GRAY2                1
 1137 #define CTX_ENABLE_GRAY4                1
 1138 #define CTX_ENABLE_GRAY8                1
 1139 #define CTX_ENABLE_GRAYA8               1
 1140 #define CTX_ENABLE_GRAYF                1
 1141 #define CTX_ENABLE_GRAYAF               1
 1142 
 1143 #define CTX_ENABLE_RGB8                 1
 1144 #define CTX_ENABLE_RGBA8                1
 1145 #define CTX_ENABLE_BGRA8                1
 1146 
 1147 #define CTX_ENABLE_RGB332               1
 1148 #define CTX_ENABLE_RGB565               1
 1149 #define CTX_ENABLE_RGB565_BYTESWAPPED   1
 1150 #define CTX_ENABLE_RGBAF                1
 1151 
 1152 #if CTX_ENABLE_CMYK
 1153 #define CTX_ENABLE_CMYK8                1
 1154 #define CTX_ENABLE_CMYKA8               1
 1155 #define CTX_ENABLE_CMYKAF               1
 1156 #endif
 1157 
 1158 #endif
 1159 
 1160 /* by including ctx-font-regular.h, or ctx-font-mono.h the
 1161  * built-in fonts using ctx renderstream encoding is enabled
 1162  */
 1163 #if CTX_FONT_regular || CTX_FONT_mono || CTX_FONT_bold \
 1164   || CTX_FONT_italic || CTX_FONT_sans || CTX_FONT_serif
 1165 #ifndef CTX_FONT_ENGINE_CTX
 1166 #define CTX_FONT_ENGINE_CTX        1
 1167 #endif
 1168 #endif
 1169 
 1170 
 1171 /* If stb_strutype.h is included before ctx.h add integration code for 
 1172 runtime loading
 1173  * of opentype fonts.
 1174  */
 1175 #ifdef __STB_INCLUDE_STB_TRUETYPE_H__
 1176 #ifndef CTX_FONT_ENGINE_STB
 1177 #define CTX_FONT_ENGINE_STB        1
 1178 #endif
 1179 #else
 1180 #define CTX_FONT_ENGINE_STB        0
 1181 #endif
 1182 
 1183 /* force add format if we have shape cache */
 1184 #if CTX_SHAPE_CACHE
 1185 #ifdef CTX_ENABLE_GRAY8
 1186 #undef CTX_ENABLE_GRAY8
 1187 #endif
 1188 #define CTX_ENABLE_GRAY8  1
 1189 #endif
 1190 
 1191 /* include the bitpack packer, can be opted out of to decrease code size
 1192  */
 1193 #ifndef CTX_BITPACK_PACKER
 1194 #define CTX_BITPACK_PACKER 1
 1195 #endif
 1196 
 1197 /* enable RGBA8 intermediate format for
 1198  *the indirectly implemented pixel-formats.
 1199  */
 1200 #if CTX_ENABLE_GRAY1 | CTX_ENABLE_GRAY2 | CTX_ENABLE_GRAY4 | 
 1201 CTX_ENABLE_RGB565 | CTX_ENABLE_RGB565_BYTESWAPPED | CTX_ENABLE_RGB8 | 
 1202 CTX_ENABLE_RGB332
 1203 
 1204   #ifdef CTX_ENABLE_RGBA8
 1205     #undef CTX_ENABLE_RGBA8
 1206   #endif
 1207   #define CTX_ENABLE_RGBA8  1
 1208 #endif
 1209 
 1210 /* enable cmykf which is cmyk intermediate format
 1211  */
 1212 #ifdef CTX_ENABLE_CMYK8
 1213 #ifdef CTX_ENABLE_CMYKF
 1214 #undef CTX_ENABLE_CMYKF
 1215 #endif
 1216 #define CTX_ENABLE_CMYKF  1
 1217 #endif
 1218 #ifdef CTX_ENABLE_CMYKA8
 1219 #ifdef CTX_ENABLE_CMYKF
 1220 #undef CTX_ENABLE_CMYKF
 1221 #endif
 1222 #define CTX_ENABLE_CMYKF  1
 1223 #endif
 1224 
 1225 #ifdef CTX_ENABLE_CMYKF8
 1226 #ifdef CTX_ENABLE_CMYK
 1227 #undef CTX_ENABLE_CMYK
 1228 #endif
 1229 #define CTX_ENABLE_CMYK   1
 1230 #endif
 1231 
 1232 #define CTX_PI                              3.141592653589793f
 1233 #ifndef CTX_RASTERIZER_MAX_CIRCLE_SEGMENTS
 1234 #define CTX_RASTERIZER_MAX_CIRCLE_SEGMENTS  100
 1235 #endif
 1236 
 1237 #ifndef CTX_MAX_FONTS
 1238 #define CTX_MAX_FONTS            3
 1239 #endif
 1240 
 1241 #ifndef CTX_MAX_STATES
 1242 #define CTX_MAX_STATES           10
 1243 #endif
 1244 
 1245 #ifndef CTX_MAX_EDGES
 1246 #define CTX_MAX_EDGES            257
 1247 #endif
 1248 
 1249 #ifndef CTX_MAX_LINGERING_EDGES
 1250 #define CTX_MAX_LINGERING_EDGES  32
 1251 #endif
 1252 
 1253 #ifndef CTX_MAX_TEXTURES
 1254 #define CTX_MAX_TEXTURES         16
 1255 #endif
 1256 
 1257 #ifndef CTX_MAX_PENDING
 1258 #define CTX_MAX_PENDING          128
 1259 #endif
 1260 
 1261 
 1262 #define CTX_RASTERIZER_EDGE_MULTIPLIER  1024
 1263 
 1264 
 1265 #define CTX_ASSERT               0
 1266 
 1267 #if CTX_ASSERT==1
 1268 #define ctx_assert(a)  if(!(a)){fprintf(stderr,"%s:%i assertion failed\n", 
 1269                    __FUNCTION__, __LINE__);  }
 1270 #else
 1271 #define ctx_assert(a)
 1272 #endif
 1273 
 1274 
 1275 #if CTX_FONTS_FROM_FILE
 1276 int   ctx_load_font_ttf_file (const char *name, const char *path);
 1277 #endif
 1278 
 1279 int ctx_get_renderstream_count (Ctx *ctx);
 1280 
 1281 
 1282 struct
 1283   _CtxCommand
 1284 {
 1285   union
 1286   {
 1287     uint8_t  code;
 1288     CtxEntry entry;
 1289     struct
 1290     {
 1291       uint8_t code;
 1292       float scalex;
 1293       float scaley;
 1294     } scale;
 1295     struct
 1296     {
 1297       uint8_t code;
 1298       uint32_t stringlen;
 1299       uint32_t blocklen;
 1300       uint8_t cont;
 1301       uint8_t data[8]; /* ... and continues */
 1302     } data;
 1303     struct
 1304     {
 1305       uint8_t code;
 1306       uint32_t stringlen;
 1307       uint32_t blocklen;
 1308     } data_rev;
 1309     struct
 1310     {
 1311       uint8_t code;
 1312       float pad;
 1313       float pad2;
 1314       uint8_t code_data;
 1315       uint32_t stringlen;
 1316       uint32_t blocklen;
 1317       uint8_t code_cont;
 1318       uint8_t utf8[8]; /* .. and continues */
 1319     } text;
 1320     struct
 1321     {
 1322       uint8_t  code;
 1323       uint32_t key_hash;
 1324       float    pad;
 1325       uint8_t  code_data;
 1326       uint32_t stringlen;
 1327       uint32_t blocklen;
 1328       uint8_t  code_cont;
 1329       uint8_t  utf8[8]; /* .. and continues */
 1330     } set;
 1331     struct
 1332     {
 1333       uint8_t  code;
 1334       uint32_t pad0;
 1335       float    pad1;
 1336       uint8_t  code_data;
 1337       uint32_t stringlen;
 1338       uint32_t blocklen;
 1339       uint8_t  code_cont;
 1340       uint8_t  utf8[8]; /* .. and continues */
 1341     } get;
 1342     struct
 1343     {
 1344       uint8_t code;
 1345       float pad;
 1346       float pad2;
 1347       uint8_t code_data;
 1348       uint32_t stringlen;
 1349       uint32_t blocklen;
 1350       uint8_t code_cont;
 1351       uint8_t utf8[8]; /* .. and continues */
 1352     } text_stroke;
 1353     struct
 1354     {
 1355       uint8_t code;
 1356       float pad;
 1357       float pad2;
 1358       uint8_t code_data;
 1359       uint32_t stringlen;
 1360       uint32_t blocklen;
 1361       uint8_t code_cont;
 1362       uint8_t utf8[8]; /* .. and continues */
 1363     } set_font;
 1364     struct
 1365     {
 1366       uint8_t code;
 1367       float model;
 1368       float r;
 1369       uint8_t pad1;
 1370       float g;
 1371       float b;
 1372       uint8_t pad2;
 1373       float a;
 1374     } rgba;
 1375     struct
 1376     {
 1377       uint8_t code;
 1378       float model;
 1379       float c;
 1380       uint8_t pad1;
 1381       float m;
 1382       float y;
 1383       uint8_t pad2;
 1384       float k;
 1385       float a;
 1386     } cmyka;
 1387     struct
 1388     {
 1389       uint8_t code;
 1390       float model;
 1391       float g;
 1392       uint8_t pad1;
 1393       float a;
 1394     } graya;
 1395     struct
 1396     {
 1397       uint8_t code;
 1398       float model;
 1399       float c0;
 1400       uint8_t pad1;
 1401       float c1;
 1402       float c2;
 1403       uint8_t pad2;
 1404       float c3;
 1405       float c4;
 1406       uint8_t pad3;
 1407       float c5;
 1408       float c6;
 1409       uint8_t pad4;
 1410       float c7;
 1411       float c8;
 1412       uint8_t pad5;
 1413       float c9;
 1414       float c10;
 1415     } set_color;
 1416     struct
 1417     {
 1418       uint8_t code;
 1419       float x;
 1420       float y;
 1421     } rel_move_to;
 1422     struct
 1423     {
 1424       uint8_t code;
 1425       float x;
 1426       float y;
 1427     } rel_line_to;
 1428     struct
 1429     {
 1430       uint8_t code;
 1431       float x;
 1432       float y;
 1433     } line_to;
 1434     struct
 1435     {
 1436       uint8_t code;
 1437       float cx1;
 1438       float cy1;
 1439       uint8_t pad0;
 1440       float cx2;
 1441       float cy2;
 1442       uint8_t pad1;
 1443       float x;
 1444       float y;
 1445     } rel_curve_to;
 1446     struct
 1447     {
 1448       uint8_t code;
 1449       float x;
 1450       float y;
 1451     } move_to;
 1452     struct
 1453     {
 1454       uint8_t code;
 1455       float cx1;
 1456       float cy1;
 1457       uint8_t pad0;
 1458       float cx2;
 1459       float cy2;
 1460       uint8_t pad1;
 1461       float x;
 1462       float y;
 1463     } curve_to;
 1464     struct
 1465     {
 1466       uint8_t code;
 1467       float x1;
 1468       float y1;
 1469       uint8_t pad0;
 1470       float r1;
 1471       float x2;
 1472       uint8_t pad1;
 1473       float y2;
 1474       float r2;
 1475     } radial_gradient;
 1476     struct
 1477     {
 1478       uint8_t code;
 1479       float x1;
 1480       float y1;
 1481       uint8_t pad0;
 1482       float x2;
 1483       float y2;
 1484     } linear_gradient;
 1485     struct
 1486     {
 1487       uint8_t code;
 1488       float x;
 1489       float y;
 1490       uint8_t pad0;
 1491       float width;
 1492       float height;
 1493       uint8_t pad1;
 1494       float radius;
 1495     } rectangle;
 1496     struct
 1497     {
 1498       uint8_t code;
 1499       uint8_t rgba[4];
 1500       uint16_t x;
 1501       uint16_t y;
 1502     } set_pixel;
 1503     struct
 1504     {
 1505       uint8_t code;
 1506       float cx;
 1507       float cy;
 1508       uint8_t pad0;
 1509       float x;
 1510       float y;
 1511     } quad_to;
 1512     struct
 1513     {
 1514       uint8_t code;
 1515       float cx;
 1516       float cy;
 1517       uint8_t pad0;
 1518       float x;
 1519       float y;
 1520     } rel_quad_to;
 1521     struct
 1522     {
 1523       uint8_t code;
 1524       float x;
 1525       float y;
 1526       uint8_t pad0;
 1527       float radius;
 1528       float angle1;
 1529       uint8_t pad1;
 1530       float angle2;
 1531       float direction;
 1532     }
 1533     arc;
 1534     struct
 1535     {
 1536       uint8_t code;
 1537       float x1;
 1538       float y1;
 1539       uint8_t pad0;
 1540       float x2;
 1541       float y2;
 1542       uint8_t pad1;
 1543       float radius;
 1544     }
 1545     arc_to;
 1546     /* some format specific generic accesors:  */
 1547     struct
 1548     {
 1549       uint8_t code;
 1550       float x0;
 1551       float y0;
 1552       uint8_t pad0;
 1553       float x1;
 1554       float y1;
 1555       uint8_t pad1;
 1556       float x2;
 1557       float y2;
 1558       uint8_t pad2;
 1559       float x3;
 1560       float y3;
 1561       uint8_t pad3;
 1562       float x4;
 1563       float y4;
 1564     } c;
 1565     struct
 1566     {
 1567       uint8_t code;
 1568       float a0;
 1569       float a1;
 1570       uint8_t pad0;
 1571       float a2;
 1572       float a3;
 1573       uint8_t pad1;
 1574       float a4;
 1575       float a5;
 1576       uint8_t pad2;
 1577       float a6;
 1578       float a7;
 1579       uint8_t pad3;
 1580       float a8;
 1581       float a9;
 1582     } f;
 1583     struct
 1584     {
 1585       uint8_t code;
 1586       uint32_t a0;
 1587       uint32_t a1;
 1588       uint8_t pad0;
 1589       uint32_t a2;
 1590       uint32_t a3;
 1591       uint8_t pad1;
 1592       uint32_t a4;
 1593       uint32_t a5;
 1594       uint8_t pad2;
 1595       uint32_t a6;
 1596       uint32_t a7;
 1597       uint8_t pad3;
 1598       uint32_t a8;
 1599       uint32_t a9;
 1600     } u32;
 1601     struct
 1602     {
 1603       uint8_t code;
 1604       uint64_t a0;
 1605       uint8_t pad0;
 1606       uint64_t a1;
 1607       uint8_t pad1;
 1608       uint64_t a2;
 1609       uint8_t pad2;
 1610       uint64_t a3;
 1611       uint8_t pad3;
 1612       uint64_t a4;
 1613     } u64;
 1614     struct
 1615     {
 1616       uint8_t code;
 1617       int32_t a0;
 1618       int32_t a1;
 1619       uint8_t pad0;
 1620       int32_t a2;
 1621       int32_t a3;
 1622       uint8_t pad1;
 1623       int32_t a4;
 1624       int32_t a5;
 1625       uint8_t pad2;
 1626       int32_t a6;
 1627       int32_t a7;
 1628       uint8_t pad3;
 1629       int32_t a8;
 1630       int32_t a9;
 1631     } s32;
 1632     struct
 1633     {
 1634       uint8_t code;
 1635       int16_t a0;
 1636       int16_t a1;
 1637       int16_t a2;
 1638       int16_t a3;
 1639       uint8_t pad0;
 1640       int16_t a4;
 1641       int16_t a5;
 1642       int16_t a6;
 1643       int16_t a7;
 1644       uint8_t pad1;
 1645       int16_t a8;
 1646       int16_t a9;
 1647       int16_t a10;
 1648       int16_t a11;
 1649       uint8_t pad2;
 1650       int16_t a12;
 1651       int16_t a13;
 1652       int16_t a14;
 1653       int16_t a15;
 1654       uint8_t pad3;
 1655       int16_t a16;
 1656       int16_t a17;
 1657       int16_t a18;
 1658       int16_t a19;
 1659     } s16;
 1660     struct
 1661     {
 1662       uint8_t code;
 1663       uint16_t a0;
 1664       uint16_t a1;
 1665       uint16_t a2;
 1666       uint16_t a3;
 1667       uint8_t pad0;
 1668       uint16_t a4;
 1669       uint16_t a5;
 1670       uint16_t a6;
 1671       uint16_t a7;
 1672       uint8_t pad1;
 1673       uint16_t a8;
 1674       uint16_t a9;
 1675       uint16_t a10;
 1676       uint16_t a11;
 1677       uint8_t pad2;
 1678       uint16_t a12;
 1679       uint16_t a13;
 1680       uint16_t a14;
 1681       uint16_t a15;
 1682       uint8_t pad3;
 1683       uint16_t a16;
 1684       uint16_t a17;
 1685       uint16_t a18;
 1686       uint16_t a19;
 1687     } u16;
 1688     struct
 1689     {
 1690       uint8_t code;
 1691       uint8_t a0;
 1692       uint8_t a1;
 1693       uint8_t a2;
 1694       uint8_t a3;
 1695       uint8_t a4;
 1696       uint8_t a5;
 1697       uint8_t a6;
 1698       uint8_t a7;
 1699       uint8_t pad0;
 1700       uint8_t a8;
 1701       uint8_t a9;
 1702       uint8_t a10;
 1703       uint8_t a11;
 1704       uint8_t a12;
 1705       uint8_t a13;
 1706       uint8_t a14;
 1707       uint8_t a15;
 1708       uint8_t pad1;
 1709       uint8_t a16;
 1710       uint8_t a17;
 1711       uint8_t a18;
 1712       uint8_t a19;
 1713       uint8_t a20;
 1714       uint8_t a21;
 1715       uint8_t a22;
 1716       uint8_t a23;
 1717     } u8;
 1718     struct
 1719     {
 1720       uint8_t code;
 1721       int8_t a0;
 1722       int8_t a1;
 1723       int8_t a2;
 1724       int8_t a3;
 1725       int8_t a4;
 1726       int8_t a5;
 1727       int8_t a6;
 1728       int8_t a7;
 1729       uint8_t pad0;
 1730       int8_t a8;
 1731       int8_t a9;
 1732       int8_t a10;
 1733       int8_t a11;
 1734       int8_t a12;
 1735       int8_t a13;
 1736       int8_t a14;
 1737       int8_t a15;
 1738       uint8_t pad1;
 1739       int8_t a16;
 1740       int8_t a17;
 1741       int8_t a18;
 1742       int8_t a19;
 1743       int8_t a20;
 1744       int8_t a21;
 1745       int8_t a22;
 1746       int8_t a23;
 1747     } s8;
 1748   };
 1749   CtxEntry next_entry; // also pads size of CtxCommand slightly.
 1750 };
 1751 
 1752 typedef struct _CtxImplementation CtxImplementation;
 1753 struct _CtxImplementation
 1754 {
 1755   void (*process) (void *renderer, CtxCommand *entry);
 1756   void (*flush)   (void *renderer);
 1757   void (*free)    (void *renderer);
 1758 };
 1759 
 1760 CtxCommand *ctx_iterator_next (CtxIterator *iterator);
 1761 
 1762 #define ctx_arg_string()  ((char*)&entry[2].data.u8[0])
 1763 
 1764 
 1765 /* The above should be public API
 1766  */
 1767 
 1768 #pragma pack(pop)
 1769 
 1770 /* access macros for nth argument of a given type when packed into
 1771  * an CtxEntry pointer in current code context
 1772  */
 1773 #define ctx_arg_float(no) entry[(no)>>1].data.f[(no)&1]
 1774 #define ctx_arg_u64(no)   entry[(no)].data.u64[0]
 1775 #define ctx_arg_u32(no)   entry[(no)>>1].data.u32[(no)&1]
 1776 #define ctx_arg_s32(no)   entry[(no)>>1].data.s32[(no)&1]
 1777 #define ctx_arg_u16(no)   entry[(no)>>2].data.u16[(no)&3]
 1778 #define ctx_arg_s16(no)   entry[(no)>>2].data.s16[(no)&3]
 1779 #define ctx_arg_u8(no)    entry[(no)>>3].data.u8[(no)&7]
 1780 #define ctx_arg_s8(no)    entry[(no)>>3].data.s8[(no)&7]
 1781 #define ctx_arg_string()  ((char*)&entry[2].data.u8[0])
 1782 
 1783 typedef enum
 1784 {
 1785   CTX_GRAY           = 1,
 1786   CTX_RGB            = 3,
 1787   CTX_DRGB           = 4,
 1788   CTX_CMYK           = 5,
 1789   CTX_DCMYK          = 6,
 1790   CTX_LAB            = 7,
 1791   CTX_LCH            = 8,
 1792   CTX_GRAYA          = 101,
 1793   CTX_RGBA           = 103,
 1794   CTX_DRGBA          = 104,
 1795   CTX_CMYKA          = 105,
 1796   CTX_DCMYKA         = 106,
 1797   CTX_LABA           = 107,
 1798   CTX_LCHA           = 108,
 1799   CTX_GRAYA_A        = 201,
 1800   CTX_RGBA_A         = 203,
 1801   CTX_RGBA_A_DEVICE  = 204,
 1802   CTX_CMYKA_A        = 205,
 1803   CTX_DCMYKA_A       = 206,
 1804   // RGB  device and  RGB  ?
 1805 } CtxColorModel;
 1806 
 1807 static inline int ctx_color_model_get_components (CtxColorModel model)
 1808 {
 1809   switch (model)
 1810     {
 1811       case CTX_GRAY:
 1812         return 1;
 1813       case CTX_GRAYA:
 1814       case CTX_GRAYA_A:
 1815         return 1;
 1816       case CTX_RGB:
 1817       case CTX_LAB:
 1818       case CTX_LCH:
 1819       case CTX_DRGB:
 1820         return 3;
 1821       case CTX_CMYK:
 1822       case CTX_DCMYK:
 1823       case CTX_LABA:
 1824       case CTX_LCHA:
 1825       case CTX_RGBA:
 1826       case CTX_DRGBA:
 1827       case CTX_RGBA_A:
 1828       case CTX_RGBA_A_DEVICE:
 1829         return 4;
 1830       case CTX_DCMYKA:
 1831       case CTX_CMYKA:
 1832       case CTX_CMYKA_A:
 1833       case CTX_DCMYKA_A:
 1834         return 5;
 1835     }
 1836   return 0;
 1837 }
 1838 
 1839 
 1840 #ifdef __cplusplus
 1841 }
 1842 #endif
 1843 #endif
 1844 
 1845 typedef struct _CtxParser CtxParser;
 1846   CtxParser *ctx_parser_new (
 1847   Ctx       *ctx,
 1848   int        width,
 1849   int        height,
 1850   float      cell_width,
 1851   float      cell_height,
 1852   int        cursor_x,
 1853   int        cursor_y,
 1854   int   (*set_prop)(void *prop_data, uint32_t key, const char *data,  int 
 1855          len),
 1856   int   (*get_prop)(void *prop_Data, const char *key, char **data, int *len)
 1857          ,
 1858   void  *prop_data,
 1859   void (*exit) (void *exit_data),
 1860   void *exit_data);
 1861 
 1862 void
 1863 ctx_parser_set_size (CtxParser *parser,
 1864                      int        width,
 1865                      int        height,
 1866                      float      cell_width,
 1867                      float      cell_height);
 1868 
 1869 void ctx_parser_feed_byte (CtxParser *parser, int byte);
 1870 
 1871 void ctx_parser_free (CtxParser *parser);
 1872 
 1873 #define CTX_CLAMP(val,min,max) ((val)<(min)?(min):(val)>(max)?(max):(val))
 1874 static inline int   ctx_mini (int a, int b)     { if (a < b) return a; 
 1875                               return b; }
 1876 static inline float ctx_minf (float a, float b) { if (a < b) return a; 
 1877                               return b; }
 1878 static inline int   ctx_maxi (int a, int b)     { if (a > b) return a; 
 1879                               return b; }
 1880 static inline float ctx_maxf (float a, float b) { if (a > b) return a; 
 1881                               return b; }
 1882 
 1883 
 1884 #ifndef __CTX_LIST__
 1885 #define __CTX_LIST__
 1886 
 1887 #include <stdlib.h>
 1888 
 1889 /* The whole ctx_list implementation is in the header and will be inlined
 1890  * wherever it is used.
 1891  */
 1892 
 1893 typedef struct _CtxList CtxList;
 1894 struct _CtxList {
 1895   void *data;
 1896   CtxList *next;
 1897   void (*freefunc)(void *data, void *freefunc_data);
 1898   void *freefunc_data;
 1899 };
 1900 
 1901 static inline void ctx_list_prepend_full (CtxList **list, void *data,
 1902     void (*freefunc)(void *data, void *freefunc_data),
 1903     void *freefunc_data)
 1904 {
 1905   CtxList *new_= (CtxList*)calloc (sizeof (CtxList), 1);
 1906   new_->next = *list;
 1907   new_->data=data;
 1908   new_->freefunc=freefunc;
 1909   new_->freefunc_data = freefunc_data;
 1910   *list = new_;
 1911 }
 1912 
 1913 static inline int ctx_list_length (CtxList *list)
 1914 {
 1915   int length = 0;
 1916   CtxList *l;
 1917   for (l = list; l; l = l->next, length++);
 1918   return length;
 1919 }
 1920 
 1921 static inline void ctx_list_prepend (CtxList **list, void *data)
 1922 {
 1923   CtxList *new_ = (CtxList*) calloc (sizeof (CtxList), 1);
 1924   new_->next= *list;
 1925   new_->data=data;
 1926   *list = new_;
 1927 }
 1928 
 1929 static inline CtxList *ctx_list_nth (CtxList *list, int no)
 1930 {
 1931   while (no-- && list)
 1932     { list = list->next; }
 1933   return list;
 1934 }
 1935 
 1936 
 1937 static inline void
 1938 ctx_list_insert_before (CtxList **list, CtxList *sibling,
 1939                        void *data)
 1940 {
 1941   if (*list == NULL || *list == sibling)
 1942     {
 1943       ctx_list_prepend (list, data);
 1944     }
 1945   else
 1946     {
 1947       CtxList *prev = NULL;
 1948       for (CtxList *l = *list; l; l=l->next)
 1949         {
 1950           if (l == sibling)
 1951             { break; }
 1952           prev = l;
 1953         }
 1954       if (prev)
 1955         {
 1956           CtxList *new_ = (CtxList*)calloc (sizeof (CtxList), 1);
 1957           new_->next = sibling;
 1958           new_->data = data;
 1959           prev->next=new_;
 1960         }
 1961     }
 1962 }
 1963 
 1964 static inline void ctx_list_remove (CtxList **list, void *data)
 1965 {
 1966   CtxList *iter, *prev = NULL;
 1967   if ((*list)->data == data)
 1968     {
 1969       if ((*list)->freefunc)
 1970         (*list)->freefunc ((*list)->data, (*list)->freefunc_data);
 1971       prev = (*list)->next;
 1972       free (*list);
 1973       *list = prev;
 1974       return;
 1975     }
 1976   for (iter = *list; iter; iter = iter->next)
 1977     if (iter->data == data)
 1978       {
 1979         if (iter->freefunc)
 1980           iter->freefunc (iter->data, iter->freefunc_data);
 1981         prev->next = iter->next;
 1982         free (iter);
 1983         break;
 1984       }
 1985     else
 1986       prev = iter;
 1987 }
 1988 
 1989 static inline void ctx_list_free (CtxList **list)
 1990 {
 1991   while (*list)
 1992     ctx_list_remove (list, (*list)->data);
 1993 }
 1994 
 1995 static inline void
 1996 ctx_list_reverse (CtxList **list)
 1997 {
 1998   CtxList *new_ = NULL;
 1999   CtxList *l;
 2000   for (l = *list; l; l=l->next)
 2001     ctx_list_prepend (&new_, l->data);
 2002   ctx_list_free (list);
 2003   *list = new_;
 2004 }
 2005 
 2006 static inline void *ctx_list_last (CtxList *list)
 2007 {
 2008   if (list)
 2009     {
 2010       CtxList *last;
 2011       for (last = list; last->next; last=last->next);
 2012       return last->data;
 2013     }
 2014   return NULL;
 2015 }
 2016 
 2017 static inline void ctx_list_append_full (CtxList **list, void *data,
 2018     void (*freefunc)(void *data, void *freefunc_data),
 2019     void *freefunc_data)
 2020 {
 2021   CtxList *new_ = (CtxList*) calloc (sizeof (CtxList), 1);
 2022   new_->data=data;
 2023   new_->freefunc = freefunc;
 2024   new_->freefunc_data = freefunc_data;
 2025   if (*list)
 2026     {
 2027       CtxList *last;
 2028       for (last = *list; last->next; last=last->next);
 2029       last->next = new_;
 2030       return;
 2031     }
 2032   *list = new_;
 2033   return;
 2034 }
 2035 
 2036 static inline void ctx_list_append (CtxList **list, void *data)
 2037 {
 2038   ctx_list_append_full (list, data, NULL, NULL);
 2039 }
 2040 
 2041 static inline void
 2042 ctx_list_insert_at (CtxList **list,
 2043                     int       no,
 2044                     void     *data)
 2045 {
 2046   if (*list == NULL || no == 0)
 2047     {
 2048       ctx_list_prepend (list, data);
 2049     }
 2050   else
 2051     {
 2052       int pos = 0;
 2053       CtxList *prev = NULL;
 2054       CtxList *sibling = NULL;
 2055       for (CtxList *l = *list; l && pos < no; l=l->next)
 2056         {
 2057           prev = sibling;
 2058           sibling = l;
 2059           pos ++;
 2060         }
 2061       if (prev)
 2062         {
 2063           CtxList *new_ = (CtxList*)calloc (sizeof (CtxList), 1);
 2064           new_->next = sibling;
 2065           new_->data = data;
 2066           prev->next=new_;
 2067           return;
 2068         }
 2069       ctx_list_append (list, data);
 2070     }
 2071 }
 2072 
 2073 static CtxList*
 2074 ctx_list_merge_sorted (CtxList* list1,
 2075                        CtxList* list2,
 2076     int(*compare)(const void *a, const void *b, void *userdata), void 
 2077         *userdata
 2078 )
 2079 {
 2080   if (list1 == NULL)
 2081      return(list2);
 2082   else if (list2==NULL)
 2083      return(list1);
 2084 
 2085   if (compare (list1->data, list2->data, userdata) >= 0)
 2086   {
 2087     list1->next = ctx_list_merge_sorted (list1->next,list2, compare, 
 2088                   userdata);
 2089     /*list1->next->prev = list1;
 2090       list1->prev = NULL;*/
 2091     return list1;
 2092   }
 2093   else
 2094   {
 2095     list2->next = ctx_list_merge_sorted (list1,list2->next, compare, 
 2096                   userdata);
 2097     /*list2->next->prev = list2;
 2098       list2->prev = NULL;*/
 2099     return list2;
 2100   }
 2101 }
 2102 
 2103 static void
 2104 ctx_list_split_half (CtxList*  head,
 2105                      CtxList** list1,
 2106                      CtxList** list2)
 2107 {
 2108   CtxList* fast;
 2109   CtxList* slow;
 2110   if (head==NULL || head->next==NULL)
 2111   {
 2112     *list1 = head;
 2113     *list2 = NULL;
 2114   }
 2115   else
 2116   {
 2117     slow = head;
 2118     fast = head->next;
 2119 
 2120     while (fast != NULL)
 2121     {
 2122       fast = fast->next;
 2123       if (fast != NULL)
 2124       {
 2125         slow = slow->next;
 2126         fast = fast->next;
 2127       }
 2128     }
 2129 
 2130     *list1 = head;
 2131     *list2 = slow->next;
 2132     slow->next = NULL;
 2133   }
 2134 }
 2135 
 2136 static inline void ctx_list_sort (CtxList **head,
 2137     int(*compare)(const void *a, const void *b, void *userdata),
 2138     void *userdata)
 2139 {
 2140   CtxList* list1;
 2141   CtxList* list2;
 2142 
 2143   /* Base case -- length 0 or 1 */
 2144   if ((*head == NULL) || ((*head)->next == NULL))
 2145   {
 2146     return;
 2147   }
 2148 
 2149   ctx_list_split_half (*head, &list1, &list2);
 2150   ctx_list_sort (&list1, compare, userdata);
 2151   ctx_list_sort (&list2, compare, userdata);
 2152   *head = ctx_list_merge_sorted (list1, list2, compare, userdata);
 2153 }
 2154 
 2155 #endif
 2156 typedef enum CtxOutputmode
 2157 {
 2158   CTX_OUTPUT_MODE_QUARTER,
 2159   CTX_OUTPUT_MODE_BRAILLE,
 2160   CTX_OUTPUT_MODE_SIXELS,
 2161   CTX_OUTPUT_MODE_GRAYS,
 2162   CTX_OUTPUT_MODE_CTX,
 2163   CTX_OUTPUT_MODE_CTX_COMPACT,
 2164   CTX_OUTPUT_MODE_UI
 2165 } CtxOutputmode;
 2166 
 2167 #define CTX_NORMALIZE(a)            (((a)=='-')?'_':(a))
 2168 #define CTX_NORMALIZE_CASEFOLDED(a) (((a)=='-')?'_':((((a)>='A')&&((a)<='Z')
 2169                                  )?(a)+32:(a)))
 2170 
 2171 
 2172 /* We use the preprocessor to compute case invariant hashes
 2173  * of strings directly, if there is collisions in our vocabulary
 2174  * the compiler tells us.
 2175  */
 2176 
 2177 #define CTX_STRHash(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a27,a12,a13) (\
 2178           (((uint32_t)CTX_NORMALIZE_CASEFOLDED(a0))+ \
 2179           (((uint32_t)CTX_NORMALIZE_CASEFOLDED(a1))*27)+ \
 2180           (((uint32_t)CTX_NORMALIZE_CASEFOLDED(a2))*27*27)+ \
 2181           (((uint32_t)CTX_NORMALIZE_CASEFOLDED(a3))*27*27*27)+ \
 2182           (((uint32_t)CTX_NORMALIZE_CASEFOLDED(a4))*27*27*27*27) + \
 2183           (((uint32_t)CTX_NORMALIZE_CASEFOLDED(a5))*27*27*27*27*27) + \
 2184           (((uint32_t)CTX_NORMALIZE_CASEFOLDED(a6))*27*27*27*27*27*27) + \
 2185           (((uint32_t)CTX_NORMALIZE_CASEFOLDED(a7))*27*27*27*27*27*27*27) + 
 2186            \
 2187           (((uint32_t)CTX_NORMALIZE_CASEFOLDED(a8))*27*27*27*27*27*27*27*27)
 2188            + \
 2189           (((uint32_t)CTX_NORMALIZE_CASEFOLDED(a9))
 2190            *27*27*27*27*27*27*27*27*27) + \
 2191           (((uint32_t)CTX_NORMALIZE_CASEFOLDED(a10))
 2192            *27*27*27*27*27*27*27*27*27*27) + \
 2193           (((uint32_t)CTX_NORMALIZE_CASEFOLDED(a27))
 2194            *27*27*27*27*27*27*27*27*27*27*27) + \
 2195           (((uint32_t)CTX_NORMALIZE_CASEFOLDED(a12))
 2196            *27*27*27*27*27*27*27*27*27*27*27*27) + \
 2197           (((uint32_t)CTX_NORMALIZE_CASEFOLDED(a13))
 2198            *27*27*27*27*27*27*27*27*27*27*27*27*27)))
 2199 
 2200 #if CTX_POSTEL_PRINCIPLED_INPUT
 2201 #define CTX_STRH(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a27,a12,a13) \
 2202     CTX_STRHash(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a27,a12,a13)
 2203 #else
 2204 #define CTX_STRH(a0,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a27,a12,a13) (\
 2205           (((uint32_t)CTX_NORMALIZE(a0))+ \
 2206           (((uint32_t)CTX_NORMALIZE(a1))*27)+ \
 2207           (((uint32_t)CTX_NORMALIZE(a2))*27*27)+ \
 2208           (((uint32_t)CTX_NORMALIZE(a3))*27*27*27)+ \
 2209           (((uint32_t)CTX_NORMALIZE(a4))*27*27*27*27) + \
 2210           (((uint32_t)CTX_NORMALIZE(a5))*27*27*27*27*27) + \
 2211           (((uint32_t)CTX_NORMALIZE(a6))*27*27*27*27*27*27) + \
 2212           (((uint32_t)CTX_NORMALIZE(a7))*27*27*27*27*27*27*27) + \
 2213           (((uint32_t)CTX_NORMALIZE(a8))*27*27*27*27*27*27*27*27) + \
 2214           (((uint32_t)CTX_NORMALIZE(a9))*27*27*27*27*27*27*27*27*27) + \
 2215           (((uint32_t)CTX_NORMALIZE(a10))*27*27*27*27*27*27*27*27*27*27) + 
 2216            \
 2217           (((uint32_t)CTX_NORMALIZE(a27))*27*27*27*27*27*27*27*27*27*27*27) 
 2218            + \
 2219           (((uint32_t)CTX_NORMALIZE(a12))
 2220            *27*27*27*27*27*27*27*27*27*27*27*27) + \
 2221           (((uint32_t)CTX_NORMALIZE(a13))
 2222            *27*27*27*27*27*27*27*27*27*27*27*27*27)))
 2223 #endif
 2224 
 2225 static inline uint32_t ctx_strhash (const char *str, int case_insensitive)
 2226 {
 2227   uint32_t ret;
 2228   if (!str) return 0;
 2229   int len = strlen (str);
 2230   if (case_insensitive)
 2231     ret =CTX_STRHash(len>=0?str[0]:0,
 2232                        len>=1?str[1]:0,
 2233                        len>=2?str[2]:0,
 2234                        len>=3?str[3]:0,
 2235                        len>=4?str[4]:0,
 2236                        len>=5?str[5]:0,
 2237                        len>=6?str[6]:0,
 2238                        len>=7?str[7]:0,
 2239                        len>=8?str[8]:0,
 2240                        len>=9?str[9]:0,
 2241                        len>=10?str[10]:0,
 2242                        len>=11?str[11]:0,
 2243                        len>=12?str[12]:0,
 2244                        len>=13?str[13]:0);
 2245   else
 2246     ret =CTX_STRH(len>=0?str[0]:0,
 2247                     len>=1?str[1]:0,
 2248                     len>=2?str[2]:0,
 2249                     len>=3?str[3]:0,
 2250                     len>=4?str[4]:0,
 2251                     len>=5?str[5]:0,
 2252                     len>=6?str[6]:0,
 2253                     len>=7?str[7]:0,
 2254                     len>=8?str[8]:0,
 2255                     len>=9?str[9]:0,
 2256                     len>=10?str[10]:0,
 2257                     len>=11?str[11]:0,
 2258                     len>=12?str[12]:0,
 2259                     len>=13?str[13]:0);
 2260                   return ret;
 2261 }
 2262 
 2263 #if CTX_FORCE_INLINES
 2264 #define CTX_INLINE  inline __attribute__((always_inline))
 2265 #else
 2266 #define CTX_INLINE  inline
 2267 #endif
 2268 
 2269 static inline float ctx_pow2 (float a) { return a * a; }
 2270 #if CTX_MATH
 2271 
 2272 static inline float
 2273 ctx_fabsf (float x)
 2274 {
 2275   union
 2276   {
 2277     float f;
 2278     uint32_t i;
 2279   } u = { x };
 2280   u.i &= 0x7fffffff;
 2281   return u.f;
 2282 }
 2283 
 2284 static inline float
 2285 ctx_invsqrtf (float x)
 2286 {
 2287   void *foo = &x;
 2288   float xhalf = 0.5f * x;
 2289   int i=* (int *) foo;
 2290   void *bar = &i;
 2291   i = 0x5f3759df - (i >> 1);
 2292   x = * (float *) bar;
 2293   x *= (1.5f - xhalf * x * x);
 2294   x *= (1.5f - xhalf * x * x); //repeating Newton-Raphson step for higher 
 2295        precision
 2296   return x;
 2297 }
 2298 
 2299 CTX_INLINE static float
 2300 ctx_sinf (float x)
 2301 {
 2302   /* source : http://mooooo.ooo/chebyshev-sine-approximation/ */
 2303   while (x < -CTX_PI)
 2304     { x += CTX_PI * 2; }
 2305   while (x > CTX_PI)
 2306     { x -= CTX_PI * 2; }
 2307   float coeffs[]=
 2308   {
 2309     -0.10132118f,           // x
 2310       0.0066208798f,         // x^3
 2311       -0.00017350505f,        // x^5
 2312       0.0000025222919f,      // x^7
 2313       -0.000000023317787f,    // x^9
 2314       0.00000000013291342f
 2315     }; // x^11
 2316   float x2 = x*x;
 2317   float p11 = coeffs[5];
 2318   float p9  = p11*x2 + coeffs[4];
 2319   float p7  = p9*x2  + coeffs[3];
 2320   float p5  = p7*x2  + coeffs[2];
 2321   float p3  = p5*x2  + coeffs[1];
 2322   float p1  = p3*x2  + coeffs[0];
 2323   return (x - CTX_PI + 0.00000008742278f) *
 2324          (x + CTX_PI - 0.00000008742278f) * p1 * x;
 2325 }
 2326 
 2327 static inline float ctx_atan2f (float y, float x)
 2328 {
 2329   float atan, z;
 2330   if ( x == 0.0f )
 2331     {
 2332       if ( y > 0.0f )
 2333         { return CTX_PI/2; }
 2334       if ( y == 0.0f )
 2335         { return 0.0f; }
 2336       return -CTX_PI/2;
 2337     }
 2338   z = y/x;
 2339   if ( ctx_fabsf ( z ) < 1.0f )
 2340     {
 2341       atan = z/ (1.0f + 0.28f*z*z);
 2342       if (x < 0.0f)
 2343         {
 2344           if ( y < 0.0f )
 2345             { return atan - CTX_PI; }
 2346           return atan + CTX_PI;
 2347         }
 2348     }
 2349   else
 2350     {
 2351       atan = CTX_PI/2 - z/ (z*z + 0.28f);
 2352       if ( y < 0.0f ) { return atan - CTX_PI; }
 2353     }
 2354   return atan;
 2355 }
 2356 
 2357 CTX_INLINE static float ctx_sqrtf (float a)
 2358 {
 2359   return 1.0f/ctx_invsqrtf (a);
 2360 }
 2361 
 2362 CTX_INLINE static float ctx_hypotf (float a, float b)
 2363 {
 2364   return ctx_sqrtf (ctx_pow2 (a)+ctx_pow2 (b) );
 2365 }
 2366 
 2367 static inline float ctx_atanf (float a)
 2368 {
 2369   return ctx_atan2f ( (a), 1.0f);
 2370 }
 2371 
 2372 static inline float ctx_asinf (float x)
 2373 {
 2374   return ctx_atanf ( (x) * (ctx_invsqrtf (1.0f-ctx_pow2 (x) ) ) );
 2375 }
 2376 
 2377 static inline float ctx_acosf (float x)
 2378 {
 2379   return ctx_atanf ( (ctx_sqrtf (1.0f-ctx_pow2 (x) ) / (x) ) );
 2380 }
 2381 
 2382 CTX_INLINE static float ctx_cosf (float a)
 2383 {
 2384   return ctx_sinf ( (a) + CTX_PI/2.0f);
 2385 }
 2386 
 2387 static inline float ctx_tanf (float a)
 2388 {
 2389   return (ctx_cosf (a) /ctx_sinf (a) );
 2390 }
 2391 static inline float
 2392 ctx_floorf (float x)
 2393 {
 2394   return (int)x; // XXX
 2395 }
 2396 static inline float
 2397 ctx_expf (float x)
 2398 {
 2399   union { uint32_t i; float f; } v =
 2400     { (1 << 23) * (x + 183.1395965) };
 2401   return v.f;
 2402 }
 2403 
 2404 /* define more trig based on having sqrt, sin and atan2 */
 2405 
 2406 #else
 2407 #include <math.h>
 2408 static inline float ctx_fabsf (float x)           { return fabsf (x); }
 2409 static inline float ctx_floorf (float x)          { return floorf (x); }
 2410 static inline float ctx_sinf (float x)            { return sinf (x); }
 2411 static inline float ctx_atan2f (float y, float x) { return atan2f (y, x); }
 2412 static inline float ctx_hypotf (float a, float b) { return hypotf (a, b); }
 2413 static inline float ctx_acosf (float a)           { return acosf (a); }
 2414 static inline float ctx_cosf (float a)            { return cosf (a); }
 2415 static inline float ctx_tanf (float a)            { return tanf (a); }
 2416 static inline float ctx_expf (float p)            { return expf (p); }
 2417 static inline float ctx_sqrtf (float a)           { return sqrtf (a); }
 2418 #endif
 2419 
 2420 #ifdef CTX_IMPLEMENTATION
 2421 #include <stdlib.h>
 2422 
 2423 /* can balloon size and gcc itself is quite good at determining what to
 2424  * inline
 2425  */
 2426 
 2427 
 2428 #if 0
 2429 static void
 2430 ctx_memset (void *ptr, uint8_t val, int length)
 2431 {
 2432   uint8_t *p = (uint8_t *) ptr;
 2433   for (int i = 0; i < length; i ++)
 2434     { p[i] = val; }
 2435 }
 2436 #else
 2437 #define ctx_memset memset
 2438 #endif
 2439 
 2440 
 2441 static inline void ctx_strcpy (char *dst, const char *src)
 2442 {
 2443   int i = 0;
 2444   for (i = 0; src[i]; i++)
 2445     { dst[i] = src[i]; }
 2446   dst[i] = 0;
 2447 }
 2448 
 2449 static char *ctx_strchr (const char *haystack, char needle)
 2450 {
 2451   const char *p = haystack;
 2452   while (*p && *p != needle)
 2453     {
 2454       p++;
 2455     }
 2456   if (*p == needle)
 2457     { return (char *) p; }
 2458   return NULL;
 2459 }
 2460 
 2461 
 2462 inline static float ctx_fast_hypotf (float x, float y)
 2463 {
 2464   if (x < 0) { x = -x; }
 2465   if (y < 0) { y = -y; }
 2466   if (x < y)
 2467     { return 0.96f * y + 0.4f * x; }
 2468   else
 2469     { return 0.96f * x + 0.4f * y; }
 2470 }
 2471 
 2472 
 2473 typedef struct _CtxRasterizer CtxRasterizer;
 2474 typedef struct _CtxGState     CtxGState;
 2475 typedef struct _CtxState      CtxState;
 2476 typedef struct _CtxMatrix     CtxMatrix;
 2477 struct
 2478   _CtxMatrix
 2479 {
 2480   float m[3][2];
 2481 };
 2482 
 2483 typedef struct _CtxSource CtxSource;
 2484 
 2485 
 2486 #define CTX_VALID_RGBA_U8     (1<<0)
 2487 #define CTX_VALID_RGBA_DEVICE (1<<1)
 2488 #if CTX_ENABLE_CM
 2489 #define CTX_VALID_RGBA        (1<<2)
 2490 #endif
 2491 #if CTX_ENABLE_CMYK
 2492 #define CTX_VALID_CMYKA       (1<<3)
 2493 #define CTX_VALID_DCMYKA      (1<<4)
 2494 #endif
 2495 #define CTX_VALID_GRAYA       (1<<5)
 2496 #define CTX_VALID_GRAYA_U8    (1<<6)
 2497 #define CTX_VALID_LABA        ((1<<7) | CTX_VALID_GRAYA)
 2498 
 2499 //_ctx_target_space (ctx, icc);
 2500 //_ctx_space (ctx);
 2501 
 2502 typedef struct _CtxColor CtxColor;
 2503 struct _CtxColor
 2504 {
 2505   uint8_t magic; // for colors used in keydb, set to a non valid start of
 2506                  // string value.
 2507   uint8_t rgba[4];
 2508   uint8_t l_u8;
 2509   uint8_t original; // the bitmask of the originally set color
 2510   uint8_t valid;    // bitmask of which members contain valid
 2511   // values, gets denser populated as more
 2512   // formats are requested from a set color.
 2513   float   device_red;
 2514   float   device_green;
 2515   float   device_blue;
 2516   float   alpha;
 2517   float   l;        // luminance and gray
 2518 #if CTX_ENABLE_LAB  // NYI
 2519   float   a;
 2520   float   b;
 2521 #endif
 2522 #if CTX_ENABLE_CMYK
 2523   float   device_cyan;
 2524   float   device_magenta;
 2525   float   device_yellow;
 2526   float   device_key;
 2527   float   cyan;
 2528   float   magenta;
 2529   float   yellow;
 2530   float   key;
 2531 #endif
 2532 
 2533 #if CTX_ENABLE_CM
 2534   int     space;   // a babl_space when not direct
 2535   // cmyk values are presumed to always be in
 2536   // ICC space and the color values set are not
 2537   // influenced by color management. RGB values
 2538   // however are. will lose prefix
 2539   float   red;
 2540   float   green;
 2541   float   blue;
 2542 #endif
 2543 };
 2544 
 2545 typedef struct _CtxGradientStop CtxGradientStop;
 2546 
 2547 struct _CtxGradientStop
 2548 {
 2549   float   pos;
 2550   CtxColor color;
 2551 };
 2552 
 2553 typedef enum _CtxSourceType CtxSourceType;
 2554 
 2555 enum _CtxSourceType
 2556 {
 2557   CTX_SOURCE_COLOR = 0,
 2558   CTX_SOURCE_IMAGE,
 2559   CTX_SOURCE_LINEAR_GRADIENT,
 2560   CTX_SOURCE_RADIAL_GRADIENT,
 2561 };
 2562 
 2563 typedef struct _CtxPixelFormatInfo CtxPixelFormatInfo;
 2564 
 2565 typedef struct _CtxBuffer CtxBuffer;
 2566 
 2567 struct _CtxBuffer
 2568 {
 2569   void               *data;
 2570   int                 width;
 2571   int                 height;
 2572   int                 stride;
 2573   int                 revision; // XXX NYI, number to update when contents 
 2574   change
 2575                                 //
 2576   CtxPixelFormatInfo *format;
 2577   void (*free_func) (void *pixels, void *user_data);
 2578   void               *user_data;
 2579 };
 2580 
 2581 void ctx_user_to_device          (CtxState *state, float *x, float *y);
 2582 void ctx_user_to_device_distance (CtxState *state, float *x, float *y);
 2583 
 2584 typedef struct _CtxGradient CtxGradient;
 2585 struct _CtxGradient
 2586 {
 2587   CtxGradientStop stops[16];
 2588   int n_stops;
 2589 };
 2590 
 2591 struct _CtxSource
 2592 {
 2593   int type;
 2594   CtxMatrix  transform;
 2595   union
 2596   {
 2597     CtxColor color;
 2598     struct
 2599     {
 2600       uint8_t rgba[4]; // shares data with set color
 2601       uint8_t pad;
 2602       float x0;
 2603       float y0;
 2604       CtxBuffer *buffer;
 2605     } image;
 2606     struct
 2607     {
 2608       float x0;
 2609       float y0;
 2610       float x1;
 2611       float y1;
 2612       float dx;
 2613       float dy;
 2614       float start;
 2615       float end;
 2616       float length;
 2617       float rdelta;
 2618     } linear_gradient;
 2619     struct
 2620     {
 2621       float x0;
 2622       float y0;
 2623       float r0;
 2624       float x1;
 2625       float y1;
 2626       float r1;
 2627       float rdelta;
 2628     } radial_gradient;
 2629   };
 2630 };
 2631 
 2632 struct _CtxGState
 2633 {
 2634   int           keydb_pos;
 2635   int           stringpool_pos;
 2636 
 2637   CtxMatrix     transform;
 2638   //CtxSource   source_stroke;
 2639   CtxSource     source;
 2640   float         global_alpha_f;
 2641   uint8_t       global_alpha_u8;
 2642 
 2643   float         line_width;
 2644   float         miter_limit;
 2645   float         font_size;
 2646 #if CTX_ENABLE_SHADOW_BLUR
 2647   float         shadow_blur;
 2648   float         shadow_offset_x;
 2649   float         shadow_offset_y;
 2650 #endif
 2651   int           clipped:1;
 2652 
 2653   int16_t       clip_min_x;
 2654   int16_t       clip_min_y;
 2655   int16_t       clip_max_x;
 2656   int16_t       clip_max_y;
 2657 
 2658 #if CTX_ENABLE_CM
 2659   int           device_space;
 2660   int           rgb_space;
 2661   int           cmyk_space;
 2662 #endif
 2663   CtxCompositingMode  compositing_mode; // bitfield refs lead to
 2664   CtxBlend                  blend_mode; // non-vectorization
 2665 
 2666   CtxColorModel color_model;
 2667   /* bitfield-pack small state-parts */
 2668   CtxLineCap                  line_cap:2;
 2669   CtxLineJoin                line_join:2;
 2670   CtxFillRule                fill_rule:1;
 2671   unsigned int                    font:6;
 2672   unsigned int                    bold:1;
 2673   unsigned int                  italic:1;
 2674 };
 2675 
 2676 typedef enum
 2677 {
 2678   CTX_TRANSFORMATION_NONE         = 0,
 2679   CTX_TRANSFORMATION_SCREEN_SPACE = 1,
 2680   CTX_TRANSFORMATION_RELATIVE     = 2,
 2681 #if CTX_BITPACK
 2682   CTX_TRANSFORMATION_BITPACK      = 4,
 2683 #endif
 2684   CTX_TRANSFORMATION_STORE_CLEAR  = 16,
 2685 } CtxTransformation;
 2686 
 2687 #define CTX_RENDERSTREAM_DOESNT_OWN_ENTRIES   64
 2688 #define CTX_RENDERSTREAM_EDGE_LIST            128
 2689 #define CTX_RENDERSTREAM_CURRENT_PATH         512
 2690 // BITPACK
 2691 
 2692 struct _CtxRenderstream
 2693 {
 2694   CtxEntry *entries;
 2695   int       count;
 2696   int       size;
 2697   uint32_t  flags;
 2698   int       bitpack_pos;  // stream is bitpacked up to this offset
 2699 };
 2700 
 2701 CtxRenderstream *ctx_copy_path      (Ctx *ctx);
 2702 CtxRenderstream *ctx_copy_path_flat (Ctx *ctx);
 2703 
 2704 #define CTX_MAX_KEYDB 64 // number of entries in keydb
 2705                          // entries are "copy-on-change" between states
 2706 
 2707 // the keydb consists of keys set to floating point values,
 2708 // that might also be interpreted as integers for enums.
 2709 //
 2710 // the hash
 2711 typedef struct _CtxKeyDbEntry CtxKeyDbEntry;
 2712 struct _CtxKeyDbEntry
 2713 {
 2714   uint32_t key;
 2715   float value;
 2716   //union { float f[1]; uint8_t u8[4]; }value;
 2717 };
 2718 
 2719 struct _CtxState
 2720 {
 2721   int           has_moved:1;
 2722   int           has_clipped:1;
 2723   float         x;
 2724   float         y;
 2725   int           min_x;
 2726   int           min_y;
 2727   int           max_x;
 2728   int           max_y;
 2729   CtxKeyDbEntry keydb[CTX_MAX_KEYDB];
 2730   char          stringpool[CTX_STRINGPOOL_SIZE];
 2731 #if CTX_GRADIENTS
 2732   CtxGradient   gradient; /* we keep only one gradient,
 2733                              this goes icky with multiple
 2734                              restores - it should really be part of
 2735                              graphics state..
 2736                              XXX, with the stringpool gradients
 2737                              can be stored there.
 2738                            */
 2739 #endif
 2740   int16_t       gstate_no;
 2741   CtxGState     gstate;
 2742   CtxGState     gstate_stack[CTX_MAX_STATES];//at end, so can be made 
 2743   dynamic
 2744 };
 2745 
 2746 
 2747 
 2748 #define STR CTX_STRH
 2749 
 2750 #define CTX_add_stop       CTX_STRH('a','d','d','_','s','t','o','p',0,0,0,0,
 2751                                     0,0)
 2752 #define CTX_addStop        CTX_STRH('a','d','d','S','t','o','p',0,0,0,0,0,0,
 2753                                     0)
 2754 #define CTX_alphabetic     CTX_STRH('a','l','p','h','a','b','e','t','i','c',
 2755                                     0,0,0,0)
 2756 #define CTX_arc            CTX_STRH('a','r','c',0,0,0,0,0,0,0,0,0,0,0)
 2757 #define CTX_arc_to         CTX_STRH('a','r','c','_','t','o',0,0,0,0,0,0,0,0)
 2758 #define CTX_arcTo          CTX_STRH('a','r','c','T','o',0,0,0,0,0,0,0,0,0)
 2759 #define CTX_begin_path     CTX_STRH('b','e','g','i','n','_','p','a','t','h',
 2760                                     0,0,0,0)
 2761 #define CTX_beginPath      CTX_STRH('b','e','g','i','n','P','a','t','h',0,0,
 2762                                     0,0,0)
 2763 #define CTX_bevel          CTX_STRH('b','e','v','e','l',0, 0, 0, 0, 0, 0, 0,
 2764                                     0,0)
 2765 #define CTX_bottom         CTX_STRH('b','o','t','t','o','m',0,0,0,0,0,0,0,0)
 2766 #define CTX_cap            CTX_STRH('c','a','p',0,0,0,0,0,0,0,0,0,0,0)
 2767 #define CTX_center         CTX_STRH('c','e','n','t','e','r', 0, 0, 0, 0, 0, 
 2768                                     0,0,0)
 2769 #define CTX_clear          CTX_STRH('c','l','e','a','r',0,0,0,0,0,0,0,0,0)
 2770 #define CTX_color          CTX_STRH('c','o','l','o','r',0,0,0,0,0,0,0,0,0)
 2771 #define CTX_copy           CTX_STRH('c','o','p','y',0,0,0,0,0,0,0,0,0,0)
 2772 #define CTX_clip           CTX_STRH('c','l','i','p',0,0,0,0,0,0,0,0,0,0)
 2773 #define CTX_close_path     CTX_STRH('c','l','o','s','e','_','p','a','t','h',
 2774                                     0,0,0,0)
 2775 #define CTX_closePath      CTX_STRH('c','l','o','s','e','P','a','t','h',0,0,
 2776                                     0,0,0)
 2777 #define CTX_cmyka          CTX_STRH('c','m','y','k','a',0,0,0,0,0,0,0,0,0)
 2778 #define CTX_cmyk           CTX_STRH('c','m','y','k',0,0,0,0,0,0,0,0,0,0)
 2779 #define CTX_cmyk_space     CTX_STRH('c','m','y','k','_','s','p','a','c','e',
 2780                                     0,0,0,0)
 2781 #define CTX_cmykSpace      CTX_STRH('c','m','y','k','S','p','a','c','e',0,0,
 2782                                     0,0,0)
 2783 #define CTX_color          CTX_STRH('c','o','l','o','r',0,0,0,0,0,0,0,0,0)
 2784 
 2785 #define CTX_blending       CTX_STRH('b','l','e','n','d','i','n','g',0,0,0,0,
 2786                                     0,0)
 2787 #define CTX_blend          CTX_STRH('b','l','e','n','d',0,0,0,0,0,0,0,0,0)
 2788 #define CTX_blending_mode  CTX_STRH('b','l','e','n','d','i','n','g','_','m',
 2789                                     'o','d','e',0)
 2790 #define CTX_blendingMode   CTX_STRH('b','l','e','n','d','i','n','g','M','o',
 2791                                     'd','e',0,0)
 2792 #define CTX_blend_mode     CTX_STRH('b','l','e','n','d','_','m','o','d','e',
 2793                                     0,0,0,0)
 2794 #define CTX_blendMode      CTX_STRH('b','l','e','n','d','M','o','d','e',0,0,
 2795                                     0,0,0)
 2796 
 2797 #define CTX_composite      CTX_STRH('c','o','m','p','o','s','i','t','i','e',
 2798                                     0,0,0,0)
 2799 #define CTX_compositing_mode CTX_STRH('c','o','m','p','o','s','i','t','i',
 2800                                       'n','g','_','m','o')
 2801 #define CTX_compositingMode CTX_STRH('c','o','m','p','o','s','i','t','i',
 2802                                      'n','g','M','o','d')
 2803 #define CTX_curve_to       CTX_STRH('c','u','r','v','e','_','t','o',0,0,0,0,
 2804                                     0,0)
 2805 #define CTX_curveTo        CTX_STRH('c','u','r','v','e','T','o',0,0,0,0,0,0,
 2806                                     0)
 2807 #define CTX_darken         CTX_STRH('d','a','r','k','e','n',0,0,0,0,0,0,0,0)
 2808 #define CTX_dcmyk_space    CTX_STRH('d','c','m','y','k','_','s','p','a','c',
 2809                                     'e',0,0,0)
 2810 #define CTX_dcmykSpace     CTX_STRH('d','c','m','y','k','S','p','a','c','e',
 2811                                     0,0,0,0)
 2812 #define CTX_destinationIn  CTX_STRH('d','e','s','t','i','n','a','t','i','o',
 2813                                     'n','I','n',0)
 2814 #define CTX_destination_in CTX_STRH('d','e','s','t','i','n','a','t','i','o',
 2815                                     'n','_','i','n')
 2816 #define CTX_destinationAtop CTX_STRH('d','e','s','t','i','n','a','t','i',
 2817                                      'o','n','A','t','o')
 2818 #define CTX_destination_atop CTX_STRH('d','e','s','t','i','n','a','t','i',
 2819                                       'o','n','_','a','t')
 2820 #define CTX_destinationOver CTX_STRH('d','e','s','t','i','n','a','t','i',
 2821                                      'o','n','O','v','e')
 2822 #define CTX_destination_over CTX_STRH('d','e','s','t','i','n','a','t','i',
 2823                                       'o','n','-','o','v')
 2824 #define CTX_destinationOut CTX_STRH('d','e','s','t','i','n','a','t','i','o',
 2825                                     'n','O','u','t')
 2826 #define CTX_destination_out CTX_STRH('d','e','s','t','i','n','a','t','i',
 2827                                      'o','n','_','o','u')
 2828 #define CTX_difference     CTX_STRH('d','i','f','f','e','r','e','n','c','e',
 2829                                     0,0,0,0)
 2830 #define CTX_done           CTX_STRH('d','o','n','e',0,0,0,0,0,0,0,0,0,0)
 2831 #define CTX_drgba          CTX_STRH('d','r','g','b','a',0,0,0,0,0,0,0,0,0)
 2832 #define CTX_drgb           CTX_STRH('d','r','g','b',0,0,0,0,0,0,0,0,0,0)
 2833 #define CTX_drgb_space     CTX_STRH('d','r','g','b','_','s','p','a','c','e',
 2834                                     0,0,0,0)
 2835 #define CTX_drgbSpace      CTX_STRH('d','r','g','b','S','p','a','c','e',0,0,
 2836                                     0,0,0)
 2837 #define CTX_end            CTX_STRH('e','n','d',0,0,0, 0, 0, 0, 0, 0, 0,0,0)
 2838 #define CTX_endfun         CTX_STRH('e','n','d','f','u','n',0,0,0,0,0,0,0,0)
 2839 
 2840 #define CTX_end_group      CTX_STRH('e','n','d','_','G','r','o','u','p',0,0,
 2841                                     0,0,0)
 2842 #define CTX_endGroup       CTX_STRH('e','n','d','G','r','o','u','p',0,0,0,0,
 2843                                     0,0)
 2844 
 2845 #define CTX_even_odd       CTX_STRH('e','v','e','n','_','o','d', 'd', 0, 0, 
 2846                                     0, 0,0,0)
 2847 #define CTX_evenOdd        CTX_STRH('e','v','e','n','O','d', 'd', 0, 0, 0, 
 2848                                     0, 0,0,0)
 2849 #define CTX_exit           CTX_STRH('e','x','i','t',0,0,0,0,0,0,0,0,0,0)
 2850 #define CTX_fill           CTX_STRH('f','i','l','l',0,0,0,0,0,0,0,0,0,0)
 2851 #define CTX_fill_rule      CTX_STRH('f','i','l','l','_','r','u','l','e',0,0,
 2852                                     0,0,0)
 2853 #define CTX_fillRule       CTX_STRH('f','i','l','l','R','u','l','e',0,0,0,0,
 2854                                     0,0)
 2855 #define CTX_flush          CTX_STRH('f','l','u','s','h',0,0,0,0,0,0,0,0,0)
 2856 #define CTX_font           CTX_STRH('f','o','n','t',0,0,0,0,0,0,0,0,0,0)
 2857 #define CTX_font_size      CTX_STRH('f','o','n','t','_','s','i','z','e',0,0,
 2858                                     0,0,0)
 2859 #define CTX_setFontSize       CTX_STRH('s','e','t','F','o','n','t','S','i',
 2860                                        'z','e',0,0,0)
 2861 #define CTX_fontSize       CTX_STRH('f','o','n','t','S','i','z','e',0,0,0,0,
 2862                                     0,0)
 2863 #define CTX_function       CTX_STRH('f','u','n','c','t','i','o','n',0,0,0,0,
 2864                                     0,0)
 2865 #define CTX_getkey         CTX_STRH('g','e','t','k','e','y',0,0,0,0,0,0,0,0)
 2866 #define CTX_global_alpha   CTX_STRH('g','l','o','b','a','l','_','a','l','p',
 2867                                     'h','a',0,0)
 2868 #define CTX_globalAlpha    CTX_STRH('g','l','o','b','a','l','A','l','p','h',
 2869                                     'a',0,0,0)
 2870 #define CTX_glyph          CTX_STRH('g','l','y','p','h',0,0,0,0,0,0,0,0,0)
 2871 #define CTX_gradient_add_stop CTX_STRH('g','r','a','d','i','e','n','t','_',
 2872                                        'a','d','d','_','s')
 2873 #define CTX_gradientAddStop CTX_STRH('g','r','a','d','i','e','n','t','A',
 2874                                      'd','d','S','t','o')
 2875 #define CTX_graya          CTX_STRH('g','r','a','y','a',0,0,0,0,0,0,0,0,0)
 2876 #define CTX_gray           CTX_STRH('g','r','a','y',0,0,0,0,0,0,0,0,0,0)
 2877 #define CTX_H
 2878 #define CTX_hanging        CTX_STRH('h','a','n','g','i','n','g',0,0,0,0,0,0,
 2879                                     0)
 2880 #define CTX_height         CTX_STRH('h','e','i','g','h','t',0,0,0,0,0,0,0,0)
 2881 #define CTX_hor_line_to    CTX_STRH('h','o','r','_','l','i','n','e','_','t',
 2882                                     'o',0,0,0)
 2883 #define CTX_horLineTo      CTX_STRH('h','o','r','L','i','n','e','T','o',0,0,
 2884                                     0,0,0)
 2885 #define CTX_hue            CTX_STRH('h','u','e',0,0,0,0,0,0,0,0,0,0,0)
 2886 #define CTX_identity       CTX_STRH('i','d','e','n','t','i','t','y',0,0,0,0,
 2887                                     0,0)
 2888 #define CTX_ideographic    CTX_STRH('i','d','e','o','g','r','a','p','h','i',
 2889                                     'c',0,0,0)
 2890 #define CTX_join           CTX_STRH('j','o','i','n',0,0,0,0,0,0,0,0,0,0)
 2891 #define CTX_laba           CTX_STRH('l','a','b','a',0,0,0,0,0,0,0,0,0,0)
 2892 #define CTX_lab            CTX_STRH('l','a','b',0,0,0,0,0,0,0,0,0,0,0)
 2893 #define CTX_lcha           CTX_STRH('l','c','h','a',0,0,0,0,0,0,0,0,0,0)
 2894 #define CTX_lch            CTX_STRH('l','c','h',0,0,0,0,0,0,0,0,0,0,0)
 2895 #define CTX_left           CTX_STRH('l','e','f','t',0,0, 0, 0, 0, 0, 0, 0,0,
 2896                                     0)
 2897 #define CTX_lighter        CTX_STRH('l','i','g','h','t','e','r',0,0,0,0,0,0,
 2898                                     0)
 2899 #define CTX_lighten        CTX_STRH('l','i','g','h','t','e','n',0,0,0,0,0,0,
 2900                                     0)
 2901 #define CTX_linear_gradient CTX_STRH('l','i','n','e','a','r','_','g','r',
 2902                                      'a','d','i','e','n')
 2903 #define CTX_linearGradient CTX_STRH('l','i','n','e','a','r','G','r','a','d',
 2904                                     'i','e','n','t')
 2905 #define CTX_line_cap       CTX_STRH('l','i','n','e','_','c','a','p',0,0,0,0,
 2906                                     0,0)
 2907 #define CTX_lineCap        CTX_STRH('l','i','n','e','C','a','p',0,0,0,0,0,0,
 2908                                     0)
 2909 #define CTX_setLineCap     CTX_STRH('s','e','t','L','i','n','e','C','a','p',
 2910                                     0,0,0,0)
 2911 #define CTX_line_height    CTX_STRH('l','i','n','e','_','h','e','i','h','t',
 2912                                     0,0,0,0)
 2913 #define CTX_line_join      CTX_STRH('l','i','n','e','_','j','o','i','n',0,0,
 2914                                     0,0,0)
 2915 #define CTX_lineJoin       CTX_STRH('l','i','n','e','J','o','i','n',0,0,0,0,
 2916                                     0,0)
 2917 #define CTX_setLineJoin    CTX_STRH('s','e','t','L','i','n','e','J','o','i',
 2918                                     'n',0,0,0)
 2919 #define CTX_line_spacing   CTX_STRH('l','i','n','e','_','s','p','a','c','i',
 2920                                     'n','g',0,0)
 2921 #define CTX_line_to        CTX_STRH('l','i','n','e','_','t','o',0,0,0,0,0,0,
 2922                                     0)
 2923 #define CTX_lineTo         CTX_STRH('l','i','n','e','T','o',0,0,0,0,0,0,0,0)
 2924 #define CTX_line_width     CTX_STRH('l','i','n','e','_','w','i','d','t','h',
 2925                                     0,0,0,0)
 2926 #define CTX_lineWidth      CTX_STRH('l','i','n','e','W','i','d','t','h',0,0,
 2927                                     0,0,0)
 2928 #define CTX_setLineWidth      CTX_STRH('s','e','t','L','i','n','e','W','i',
 2929                                        'd','t','h',0,0)
 2930 #define CTX_view_box       CTX_STRH('v','i','e','w','_','b','o','x',0,0,0,0,
 2931                                     0,0)
 2932 #define CTX_viewBox        CTX_STRH('v','i','e','w','B','o','x',0,0,0,0,0,0,
 2933                                     0)
 2934 #define CTX_middle         CTX_STRH('m','i','d','d','l','e',0, 0, 0, 0, 0, 
 2935                                     0,0,0)
 2936 #define CTX_miter          CTX_STRH('m','i','t','e','r',0, 0, 0, 0, 0, 0, 0,
 2937                                     0,0)
 2938 #define CTX_miter_limit    CTX_STRH('m','i','t','e','r','_','l','i','m','i',
 2939                                     't',0,0,0)
 2940 #define CTX_miterLimit     CTX_STRH('m','i','t','e','r','L','i','m','i','t',
 2941                                     0,0,0,0)
 2942 #define CTX_move_to        CTX_STRH('m','o','v','e','_','t','o',0,0,0,0,0,0,
 2943                                     0)
 2944 #define CTX_moveTo         CTX_STRH('m','o','v','e','T','o',0,0,0,0,0,0,0,0)
 2945 #define CTX_multiply       CTX_STRH('m','u','l','t','i','p','l','y',0,0,0,0,
 2946                                     0,0)
 2947 #define CTX_new_page       CTX_STRH('n','e','w','_','p','a','g','e',0,0,0,0,
 2948                                     0,0)
 2949 #define CTX_newPage        CTX_STRH('n','e','w','P','a','g','e',0,0,0,0,0,0,
 2950                                     0)
 2951 #define CTX_new_path       CTX_STRH('n','e','w','_','p','a','t','h',0,0,0,0,
 2952                                     0,0)
 2953 #define CTX_newPath        CTX_STRH('n','e','w','P','a','t','h',0,0,0,0,0,0,
 2954                                     0)
 2955 #define CTX_new_state      CTX_STRH('n','e','w','_','s','t','a','t','e',0,0,
 2956                                     0,0,0)
 2957 #define CTX_none           CTX_STRH('n','o','n','e', 0 ,0, 0, 0, 0, 0, 0, 0,
 2958                                     0,0)
 2959 #define CTX_quad_to        CTX_STRH('q','u','a','d','_','t','o',0,0,0,0,0,0,
 2960                                     0)
 2961 #define CTX_quadTo         CTX_STRH('q','u','a','d','T','o',0,0,0,0,0,0,0,0)
 2962 #define CTX_radial_gradient CTX_STRH('r','a','d','i','a','l','_','g','r',
 2963                                      'a','d','i','e','n')
 2964 #define CTX_radialGradient  CTX_STRH('r','a','d','i','a','l','G','r','a',
 2965                                      'd','i','e','n','t')
 2966 #define CTX_rectangle      CTX_STRH('r','e','c','t','a','n','g','l','e',0,0,
 2967                                     0,0,0)
 2968 #define CTX_rect           CTX_STRH('r','e','c','t',0,0,0,0,0,0,0,0,0,0)
 2969 #define CTX_rel_arc_to     CTX_STRH('r','e','l','_','a','r','c','_','t','o',
 2970                                     0,0,0,0)
 2971 #define CTX_relArcTo       CTX_STRH('r','e','l','A','r','c','T','o',0,0,0,0,
 2972                                     0,0)
 2973 #define CTX_rel_curve_to   CTX_STRH('r','e','l','_','c','u','r','v','e','_',
 2974                                     't','o',0,0)
 2975 #define CTX_relCurveTo     CTX_STRH('r','e','l','C','u','r','v','e','T','o',
 2976                                     0,0,0,0)
 2977 #define CTX_rel_hor_line_to CTX_STRH('r','e','l','_','h','o','r','_','l',
 2978                                      'i','n','e',0,0)
 2979 #define CTX_relHorLineTo   CTX_STRH('r','e','l','H','o','r','L','i','n','e',
 2980                                     'T','o',0,0)
 2981 #define CTX_rel_line_to    CTX_STRH('r','e','l','_','l','i','n','e','_','t',
 2982                                     'o',0,0,0)
 2983 #define CTX_relLineTo      CTX_STRH('r','e','l','L','i','n','e','T','o',0,0,
 2984                                     0,0,0)
 2985 #define CTX_rel_move_to    CTX_STRH('r','e','l','_','m','o','v','e','_','t',
 2986                                     'o',0,0,0)
 2987 #define CTX_relMoveTo      CTX_STRH('r','e','l','M','o','v','e','T','o',0,0,
 2988                                     0,0,0)
 2989 #define CTX_rel_quad_to    CTX_STRH('r','e','l','_','q','u','a','d','_','t',
 2990                                     'o',0,0,0)
 2991 #define CTX_relQuadTo      CTX_STRH('r','e','l','Q','u','a','d','T','o',0,0,
 2992                                     0,0,0)
 2993 #define CTX_rel_smoothq_to CTX_STRH('r','e','l','_','s','m','o','o','t','h',
 2994                                     'q','_','t','o')
 2995 #define CTX_relSmoothqTo   CTX_STRH('r','e','l','S','m','o','o','t','h','q',
 2996                                     'T','o',0,0)
 2997 #define CTX_rel_smooth_to  CTX_STRH('r','e','l','_','s','m','o','o','t','h',
 2998                                     '_','t','o',0)
 2999 #define CTX_relSmoothTo    CTX_STRH('r','e','l','S','m','o','o','t','h','T',
 3000                                     'o',0,0,0)
 3001 #define CTX_rel_ver_line_to CTX_STRH('r','e','l','_','v','e','r','_','l',
 3002                                      'i','n','e',0,0)
 3003 #define CTX_relVerLineTo   CTX_STRH('r','e','l','V','e','r','L','i','n','e',
 3004                                     'T','o',0,0)
 3005 #define CTX_restore        CTX_STRH('r','e','s','t','o','r','e',0,0,0,0,0,0,
 3006                                     0)
 3007 #define CTX_reset          CTX_STRH('r','e','s','e','t',0,0,0,0,0,0,0,0,0)
 3008 #define CTX_rgba           CTX_STRH('r','g','b','a',0,0,0,0,0,0,0,0,0,0)
 3009 #define CTX_rgb            CTX_STRH('r','g','b',0,0,0,0,0,0,0,0,0,0,0)
 3010 #define CTX_rgb_space      CTX_STRH('r','g','b','_','s','p','a','c','e',0,0,
 3011                                     0,0,0)
 3012 #define CTX_rgbSpace       CTX_STRH('r','g','b','S','p','a','c','e',0,0,0,0,
 3013                                     0,0)
 3014 #define CTX_right          CTX_STRH('r','i','g','h','t',0, 0, 0, 0, 0, 0, 0,
 3015                                     0,0)
 3016 #define CTX_rotate         CTX_STRH('r','o','t','a','t','e',0,0,0,0,0,0,0,0)
 3017 #define CTX_round          CTX_STRH('r','o','u','n','d',0, 0, 0, 0, 0, 0, 0,
 3018                                     0,0)
 3019 #define CTX_round_rectangle CTX_STRH('r','o','u','n','d','_','r','e','c',
 3020                                      't','a','n','g','l')
 3021 #define CTX_roundRectangle  CTX_STRH('r','o','u','n','d','R','e','c','t',
 3022                                      'a','n','g','l','e')
 3023 #define CTX_save           CTX_STRH('s','a','v','e',0,0,0,0,0,0,0,0,0,0)
 3024 #define CTX_save           CTX_STRH('s','a','v','e',0,0,0,0,0,0,0,0,0,0)
 3025 #define CTX_scale          CTX_STRH('s','c','a','l','e',0,0,0,0,0,0,0,0,0)
 3026 #define CTX_screen         CTX_STRH('s','c','r','e','e','n',0,0,0,0,0,0,0,0)
 3027 #define CTX_setkey         CTX_STRH('s','e','t','k','e','y',0,0,0,0,0,0,0,0)
 3028 #define CTX_shadowBlur     CTX_STRH('s','h','a','d','o','w','B','l','u','r',
 3029                                     0,0,0,0)
 3030 #define CTX_shadowColor    CTX_STRH('s','h','a','d','o','w','C','o','l','o',
 3031                                     'r',0,0,0)
 3032 #define CTX_shadowOffsetX  CTX_STRH('s','h','a','d','o','w','O','f','f','s',
 3033                                     'e','t','X',0)
 3034 #define CTX_shadowOffsetY  CTX_STRH('s','h','a','d','o','w','O','f','f','s',
 3035                                     'e','t','Y',0)
 3036 #define CTX_smooth_quad_to CTX_STRH('s','m','o','o','t','h','_','q','u','a',
 3037                                     'd','_','t','o')
 3038 #define CTX_smoothQuadTo   CTX_STRH('s','m','o','o','t','h','Q','u','a','d',
 3039                                     'T','o',0,0)
 3040 #define CTX_smooth_to      CTX_STRH('s','m','o','o','t','h','_','t','o',0,0,
 3041                                     0,0,0)
 3042 #define CTX_smoothTo       CTX_STRH('s','m','o','o','t','h','T','o',0,0,0,0,
 3043                                     0,0)
 3044 #define CTX_sourceIn       CTX_STRH('s','o','u','r','c','e','I','n',0,0,0,0,
 3045                                     0,0)
 3046 #define CTX_source_in      CTX_STRH('s','o','u','r','c','e','_','i','n',0,0,
 3047                                     0,0,0)
 3048 #define CTX_sourceAtop     CTX_STRH('s','o','u','r','c','e','A','t','o','p',
 3049                                     0,0,0,0)
 3050 #define CTX_source_atop    CTX_STRH('s','o','u','r','c','e','_','a','t','o',
 3051                                     'p',0,0,0)
 3052 #define CTX_sourceOut      CTX_STRH('s','o','u','r','c','e','O','u','t',0,0,
 3053                                     0,0,0)
 3054 #define CTX_source_out     CTX_STRH('s','o','u','r','c','e','_','o','u','t',
 3055                                     0,0,0,0)
 3056 #define CTX_sourceOver     CTX_STRH('s','o','u','r','c','e','O','v','e','r',
 3057                                     0,0,0,0)
 3058 #define CTX_source_over    CTX_STRH('s','o','u','r','c','e','_','o','v','e',
 3059                                     'r',0,0,0)
 3060 #define CTX_square         CTX_STRH('s','q','u','a','r','e', 0, 0, 0, 0, 0, 
 3061                                     0,0,0)
 3062 #define CTX_start          CTX_STRH('s','t','a','r','t',0, 0, 0, 0, 0, 0, 0,
 3063                                     0,0)
 3064 #define CTX_start_move     CTX_STRH('s','t','a','r','t','_','m','o','v','e',
 3065                                     0,0,0,0)
 3066 #define CTX_start_group    CTX_STRH('s','t','a','r','t','_','G','r','o','u',
 3067                                     'p',0,0,0)
 3068 #define CTX_startGroup     CTX_STRH('s','t','a','r','t','G','r','o','u','p',
 3069                                     0,0,0,0)
 3070 #define CTX_stroke         CTX_STRH('s','t','r','o','k','e',0,0,0,0,0,0,0,0)
 3071 #define CTX_text_align     CTX_STRH('t','e','x','t','_','a','l','i','g','n',
 3072                                     0, 0,0,0)
 3073 #define CTX_textAlign      CTX_STRH('t','e','x','t','A','l','i','g','n',0, 
 3074                                     0, 0,0,0)
 3075 #define CTX_texture        CTX_STRH('t','e','x','t','u','r','e',0,0,0, 0, 0,
 3076                                     0,0)
 3077 #define CTX_text_baseline  CTX_STRH('t','e','x','t','_','b','a','s','e','l',
 3078                                     'i','n','e',0)
 3079 #define CTX_text_baseline  CTX_STRH('t','e','x','t','_','b','a','s','e','l',
 3080                                     'i','n','e',0)
 3081 #define CTX_textBaseline   CTX_STRH('t','e','x','t','B','a','s','e','l','i',
 3082                                     'n','e',0,0)
 3083 #define CTX_text           CTX_STRH('t','e','x','t',0,0,0,0,0,0,0,0,0,0)
 3084 #define CTX_text_direction CTX_STRH('t','e','x','t','_','d','i','r','e','c',
 3085                                     't','i','o','n')
 3086 #define CTX_textDirection  CTX_STRH('t','e','x','t','D','i','r','e','c','t',
 3087                                     'i','o','n',0)
 3088 #define CTX_text_indent    CTX_STRH('t','e','x','t','_','i','n','d','e','n',
 3089                                     't', 0,0,0)
 3090 #define CTX_text_stroke    CTX_STRH('t','e','x','t','_','s','t','r','o','k',
 3091                                     'e', 0,0,0)
 3092 #define CTX_textStroke     CTX_STRH('t','e','x','t','S','t','r','o','k','e',
 3093                                     0, 0,0,0)
 3094 #define CTX_top            CTX_STRH('t','o','p',0,0,0, 0, 0, 0, 0, 0, 0,0,0)
 3095 #define CTX_transform      CTX_STRH('t','r','a','n','s','f','o','r','m',0,0,
 3096                                     0,0,0)
 3097 #define CTX_translate      CTX_STRH('t','r','a','n','s','l','a','t','e',0,0,
 3098                                     0,0,0)
 3099 #define CTX_verLineTo      CTX_STRH('v','e','r','L','i','n','e','T','o',0,0,
 3100                                     0,0,0)
 3101 #define CTX_ver_line_to    CTX_STRH('v','e','r','_','l','i','n','e','_','t',
 3102                                     'o',0,0,0)
 3103 #define CTX_width          CTX_STRH('w','i','d','t','h',0,0,0,0,0,0,0,0,0)
 3104 #define CTX_winding        CTX_STRH('w','i','n','d','i','n', 'g', 0, 0, 0, 
 3105                                     0, 0,0,0)
 3106 #define CTX_x              CTX_STRH('x',0,0,0,0,0,0,0,0,0,0,0,0,0)
 3107 #define CTX_xor            CTX_STRH('x','o','r',0,0,0,0,0,0,0,0,0,0,0)
 3108 #define CTX_y              CTX_STRH('y',0,0,0,0,0,0,0,0,0,0,0,0,0)
 3109 
 3110 static float ctx_state_get (CtxState *state, uint32_t hash)
 3111 {
 3112   for (int i = state->gstate.keydb_pos-1; i>=0; i--)
 3113     {
 3114       if (state->keydb[i].key == hash)
 3115         { return state->keydb[i].value; }
 3116     }
 3117   return -0.0;
 3118 }
 3119 
 3120 static void ctx_state_set (CtxState *state, uint32_t key, float value)
 3121 {
 3122   if (key != CTX_new_state)
 3123     {
 3124       if (ctx_state_get (state, key) == value)
 3125         { return; }
 3126       for (int i = state->gstate.keydb_pos-1;
 3127            state->keydb[i].key != CTX_new_state && i >=0;
 3128            i--)
 3129         {
 3130           if (state->keydb[i].key == key)
 3131             {
 3132               state->keydb[i].value = value;
 3133               return;
 3134             }
 3135         }
 3136     }
 3137   if (state->gstate.keydb_pos >= CTX_MAX_KEYDB)
 3138     { return; }
 3139   state->keydb[state->gstate.keydb_pos].key = key;
 3140   state->keydb[state->gstate.keydb_pos].value = value;
 3141   state->gstate.keydb_pos++;
 3142 }
 3143 
 3144 
 3145 #define CTX_KEYDB_STRING_START (-80000.0)
 3146 #define CTX_KEYDB_STRING_END   (CTX_KEYDB_STRING_START + 
 3147                                 CTX_STRINGPOOL_SIZE)
 3148 
 3149 static int ctx_float_is_string (float val)
 3150 {
 3151   return val >= CTX_KEYDB_STRING_START && val <= CTX_KEYDB_STRING_END;
 3152 }
 3153 
 3154 static int ctx_float_to_string_index (float val)
 3155 {
 3156   int idx = -1;
 3157   if (ctx_float_is_string (val))
 3158   {
 3159     idx = val - CTX_KEYDB_STRING_START;
 3160   }
 3161   return idx;
 3162 }
 3163 
 3164 static float ctx_string_index_to_float (int index)
 3165 {
 3166   return CTX_KEYDB_STRING_START + index;
 3167 }
 3168 
 3169 void *ctx_state_get_blob (CtxState *state, uint32_t key)
 3170 {
 3171   float stored = ctx_state_get (state, key);
 3172   int idx = ctx_float_to_string_index (stored);
 3173   if (idx >= 0)
 3174   {
 3175      return &state->stringpool[idx];
 3176   }
 3177   // format number as string?
 3178   return NULL;
 3179 }
 3180 
 3181 const char *ctx_state_get_string (CtxState *state, uint32_t key)
 3182 {
 3183   const char *ret = (char*)ctx_state_get_blob (state, key);
 3184   if (ret && ret[0] == 127)
 3185     return NULL;
 3186   return ret;
 3187 }
 3188 
 3189 static int ctx_str_is_number (const char *str)
 3190 {
 3191   int got_digit = 0;
 3192   for (int i = 0; str[i]; i++)
 3193   {
 3194     if (str[i] >= '0' && str[i] <= '9')
 3195     {
 3196        got_digit ++;
 3197     }
 3198     else if (str[i] == '.')
 3199     {
 3200     }
 3201     else
 3202       return 0;
 3203   }
 3204   if (got_digit)
 3205     return 1;
 3206   return 0;
 3207 }
 3208 
 3209 static void ctx_state_set_blob (CtxState *state, uint32_t key, uint8_t 
 3210                                 *data, int len)
 3211 {
 3212   int idx = state->gstate.stringpool_pos;
 3213 
 3214   if (idx + len > CTX_STRINGPOOL_SIZE)
 3215   {
 3216     fprintf (stderr, "blowing varpool size [%c%c%c..]\n", data[0],data[1], 
 3217              data[1]?data[2]:0);
 3218 #if 0
 3219     for (int i = 0; i< CTX_STRINGPOOL_SIZE; i++)
 3220     {
 3221        if (i==0) fprintf (stderr, "\n%i ", i);
 3222        else      fprintf (stderr, "%c", state->stringpool[i]);
 3223     }
 3224 #endif
 3225     return;
 3226   }
 3227 
 3228   memcpy (&state->stringpool[idx], data, len);
 3229   state->gstate.stringpool_pos+=len;
 3230   state->stringpool[state->gstate.stringpool_pos++]=0;
 3231   ctx_state_set (state, key, ctx_string_index_to_float (idx));
 3232 }
 3233 
 3234 static void ctx_state_set_string (CtxState *state, uint32_t key, const char 
 3235                                   *string)
 3236 {
 3237   float old_val = ctx_state_get (state, key);
 3238   int   old_idx = ctx_float_to_string_index (old_val);
 3239 
 3240   if (old_idx >= 0)
 3241   {
 3242     const char *old_string = ctx_state_get_string (state, key);
 3243     if (old_string && !strcmp (old_string, string))
 3244       return;
 3245   }
 3246 
 3247   if (ctx_str_is_number (string))
 3248   {
 3249     ctx_state_set (state, key, strtod (string, NULL));
 3250     return;
 3251   }
 3252   // should do same with color
 3253  
 3254   // XXX should special case when the string modified is at the
 3255   //     end of the stringpool.
 3256   ctx_state_set_blob (state, key, (uint8_t*)string, strlen(string));
 3257 }
 3258 
 3259 static int ctx_state_get_color (CtxState *state, uint32_t key, CtxColor 
 3260                                 *color)
 3261 {
 3262   CtxColor *stored = (CtxColor*)ctx_state_get_blob (state, key);
 3263   if (stored)
 3264   {
 3265     if (stored->magic == 127)
 3266     {
 3267       *color = *stored;
 3268       return 0;
 3269     }
 3270   }
 3271   return -1;
 3272 }
 3273 
 3274 static void ctx_state_set_color (CtxState *state, uint32_t key, CtxColor 
 3275                                  *color)
 3276 {
 3277   CtxColor mod_color;
 3278   CtxColor old_color;
 3279   mod_color = *color;
 3280   mod_color.magic = 127;
 3281   if (ctx_state_get_color (state, key, &old_color)==0)
 3282   {
 3283     if (!memcmp (&mod_color, &old_color, sizeof (mod_color)))
 3284       return;
 3285   }
 3286   ctx_state_set_blob (state, key, (uint8_t*)&mod_color, sizeof (CtxColor));
 3287 }
 3288 
 3289 static uint8_t ctx_float_to_u8 (float val_f)
 3290 {
 3291    return (val_f * 255.99f);
 3292 #if 0
 3293   int val_i = val_f * 255.999f;
 3294   if (val_i < 0) { return 0; }
 3295   else if (val_i > 255) { return 255; }
 3296   return val_i;
 3297 #endif
 3298 }
 3299 
 3300 #if 0
 3301 
 3302 inline static float ctx_u8_to_float (uint8_t val_u8)
 3303 {
 3304   float val_f = val_u8 / 255.0;
 3305   return val_f;
 3306 }
 3307 #else
 3308 static float ctx_u8_float[256];
 3309 #define ctx_u8_to_float(val_u8) ctx_u8_float[((uint8_t)(val_u8))]
 3310 //#define ctx_u8_to_float(val_u8) (val_u8/255.0f)
 3311 
 3312 #endif
 3313 
 3314 static void ctx_color_set_RGBA8 (CtxState *state, CtxColor *color, uint8_t 
 3315                                  r, uint8_t g, uint8_t b, uint8_t a)
 3316 {
 3317   color->original = color->valid = CTX_VALID_RGBA_U8;
 3318   color->rgba[0] = r;
 3319   color->rgba[1] = g;
 3320   color->rgba[2] = b;
 3321   color->rgba[3] = a;
 3322 #if CTX_ENABLE_CM
 3323   color->space = state->gstate.device_space;
 3324 #endif
 3325 }
 3326 
 3327 #if 0
 3328 static void ctx_color_set_RGBA8_ (CtxColor *color, const uint8_t *in)
 3329 {
 3330   ctx_color_set_RGBA8 (color, in[0], in[1], in[2], in[3]);
 3331 }
 3332 #endif
 3333 
 3334 static void ctx_color_set_graya (CtxState *state, CtxColor *color, float 
 3335                                  gray, float alpha)
 3336 {
 3337   color->original = color->valid = CTX_VALID_GRAYA;
 3338   color->l = gray;
 3339   color->alpha = alpha;
 3340 }
 3341 #if 0
 3342 static void ctx_color_set_graya_ (CtxColor *color, const float *in)
 3343 {
 3344   return ctx_color_set_graya (color, in[0], in[1]);
 3345 }
 3346 #endif
 3347 
 3348 static void ctx_color_set_rgba (CtxState *state, CtxColor *color, float r, 
 3349                                 float g, float b, float a)
 3350 {
 3351 #if CTX_ENABLE_CM
 3352   color->original = color->valid = CTX_VALID_RGBA;
 3353   color->red      = r;
 3354   color->green    = g;
 3355   color->blue     = b;
 3356   color->space    = state->gstate.rgb_space;
 3357 #else
 3358   color->original     = color->valid = CTX_VALID_RGBA_DEVICE;
 3359   color->device_red   = r;
 3360   color->device_green = g;
 3361   color->device_blue  = b;
 3362 #endif
 3363   color->alpha        = a;
 3364 }
 3365 
 3366 static void ctx_color_set_drgba (CtxState *state, CtxColor *color, float r, 
 3367                                  float g, float b, float a)
 3368 {
 3369 #if CTX_ENABLE_CM
 3370   color->original     = color->valid = CTX_VALID_RGBA_DEVICE;
 3371   color->device_red   = r;
 3372   color->device_green = g;
 3373   color->device_blue  = b;
 3374   color->alpha        = a;
 3375   color->space = state->gstate.device_space;
 3376 #else
 3377   ctx_color_set_rgba (state, color, r, g, b, a);
 3378 #endif
 3379 }
 3380 
 3381 #if 0
 3382 static void ctx_color_set_rgba_ (CtxState *state, CtxColor *color, const 
 3383                                  float *in)
 3384 {
 3385   ctx_color_set_rgba (color, in[0], in[1], in[2], in[3]);
 3386 }
 3387 #endif
 3388 
 3389 /* the baseline conversions we have whether CMYK support is enabled or not,
 3390  * providing an effort at right rendering
 3391  */
 3392 static void ctx_cmyk_to_rgb (float c, float m, float y, float k, float *r, 
 3393                              float *g, float *b)
 3394 {
 3395   *r = (1.0f-c) * (1.0f-k);
 3396   *g = (1.0f-m) * (1.0f-k);
 3397   *b = (1.0f-y) * (1.0f-k);
 3398 }
 3399 
 3400 static void ctx_rgb_to_cmyk (float r, float g, float b,
 3401                              float *c_out, float *m_out, float *y_out, 
 3402                              float *k_out)
 3403 {
 3404   float c = 1.0f - r;
 3405   float m = 1.0f - g;
 3406   float y = 1.0f - b;
 3407   float k = ctx_minf (c, ctx_minf (y, m) );
 3408   if (k < 1.0f)
 3409     {
 3410       c = (c - k) / (1.0f - k);
 3411       m = (m - k) / (1.0f - k);
 3412       y = (y - k) / (1.0f - k);
 3413     }
 3414   else
 3415     {
 3416       c = m = y = 0.0f;
 3417     }
 3418   *c_out = c;
 3419   *m_out = m;
 3420   *y_out = y;
 3421   *k_out = k;
 3422 }
 3423 
 3424 #if CTX_ENABLE_CMYK
 3425 static void ctx_color_set_cmyka (CtxState *state, CtxColor *color, float c, 
 3426                                  float m, float y, float k, float a)
 3427 {
 3428   color->original = color->valid = CTX_VALID_CMYKA;
 3429   color->cyan     = c;
 3430   color->magenta  = m;
 3431   color->yellow   = y;
 3432   color->key      = k;
 3433   color->alpha    = a;
 3434 #if CTX_ENABLE_CM
 3435   color->space    = state->gstate.cmyk_space;
 3436 #endif
 3437 }
 3438 
 3439 static void ctx_color_set_dcmyka (CtxState *state, CtxColor *color, float c,
 3440                                   float m, float y, float k, float a)
 3441 {
 3442   color->original       = color->valid = CTX_VALID_DCMYKA;
 3443   color->device_cyan    = c;
 3444   color->device_magenta = m;
 3445   color->device_yellow  = y;
 3446   color->device_key     = k;
 3447   color->alpha          = a;
 3448 #if CTX_ENABLE_CM
 3449   color->space = state->gstate.cmyk_space;
 3450 #endif
 3451 }
 3452 
 3453 #endif
 3454 
 3455 #if CTX_ENABLE_CM
 3456 
 3457 static void ctx_rgb_user_to_device (CtxState *state, float rin, float gin, 
 3458                                     float bin,
 3459                                     float *rout, float *gout, float *bout)
 3460 {
 3461   /* babl plug-in point */
 3462   *rout = rin ;
 3463   *gout = gin ;
 3464   *bout = bin ;
 3465 }
 3466 
 3467 static void ctx_rgb_device_to_user (CtxState *state, float rin, float gin, 
 3468                                     float bin,
 3469                                     float *rout, float *gout, float *bout)
 3470 {
 3471   /* babl plug-in point */
 3472   *rout = rin ;
 3473   *gout = gin ;
 3474   *bout = bin ;
 3475 }
 3476 #endif
 3477 
 3478 static void ctx_color_get_drgba (CtxState *state, CtxColor *color, float 
 3479                                  *out)
 3480 {
 3481   if (! (color->valid & CTX_VALID_RGBA_DEVICE) )
 3482     {
 3483 #if CTX_ENABLE_CM
 3484       if (color->valid & CTX_VALID_RGBA)
 3485         {
 3486           ctx_rgb_user_to_device (state, color->red, color->green, color->
 3487                                   blue,
 3488                                   & (color->device_red), & (color->
 3489                                      device_green), & (color->device_blue) )
 3490                                      ;
 3491         }
 3492       else
 3493 #endif
 3494         if (color->valid & CTX_VALID_RGBA_U8)
 3495           {
 3496             color->device_red   = ctx_u8_to_float (color->rgba[0]);
 3497             color->device_green = ctx_u8_to_float (color->rgba[1]);
 3498             color->device_blue  = ctx_u8_to_float (color->rgba[2]);
 3499             color->alpha        = ctx_u8_to_float (color->rgba[3]);
 3500           }
 3501 #if CTX_ENABLE_CMYK
 3502         else if (color->valid & CTX_VALID_CMYKA)
 3503           {
 3504             ctx_cmyk_to_rgb (color->cyan, color->magenta, color->yellow, 
 3505                              color->key,
 3506                              &color->device_red,
 3507                              &color->device_green,
 3508                              &color->device_blue);
 3509           }
 3510 #endif
 3511         else if (color->valid & CTX_VALID_GRAYA)
 3512           {
 3513             color->device_red   =
 3514               color->device_green =
 3515                 color->device_blue  = color->l;
 3516           }
 3517       color->valid |= CTX_VALID_RGBA_DEVICE;
 3518     }
 3519   out[0] = color->device_red;
 3520   out[1] = color->device_green;
 3521   out[2] = color->device_blue;
 3522   out[3] = color->alpha;
 3523 }
 3524 
 3525 CTX_INLINE static void ctx_color_get_rgba (CtxState *state, CtxColor *color,
 3526                                            float *out)
 3527 {
 3528 #if CTX_ENABLE_CM
 3529   if (! (color->valid & CTX_VALID_RGBA) )
 3530     {
 3531       ctx_color_get_drgba (state, color, out);
 3532       if (color->valid & CTX_VALID_RGBA_DEVICE)
 3533         {
 3534           ctx_rgb_device_to_user (state, color->device_red, color->
 3535                                   device_green, color->device_blue,
 3536                                   & (color->red), & (color->green), & (
 3537                                      color->blue) );
 3538         }
 3539       color->valid |= CTX_VALID_RGBA;
 3540     }
 3541   out[0] = color->red;
 3542   out[1] = color->green;
 3543   out[2] = color->blue;
 3544   out[3] = color->alpha;
 3545 #else
 3546   ctx_color_get_drgba (state, color, out);
 3547 #endif
 3548 }
 3549 
 3550 #define CTX_CSS_LUMINANCE_RED   0.3f
 3551 #define CTX_CSS_LUMINANCE_GREEN 0.59f
 3552 #define CTX_CSS_LUMINANCE_BLUE  0.11f
 3553 
 3554 /* works on both float and uint8_t */
 3555 #define CTX_CSS_RGB_TO_LUMINANCE(rgb)  (\
 3556   (rgb[0]) * CTX_CSS_LUMINANCE_RED + \
 3557   (rgb[1]) * CTX_CSS_LUMINANCE_GREEN +\
 3558   (rgb[2]) * CTX_CSS_LUMINANCE_BLUE)
 3559 
 3560 CTX_INLINE static float ctx_float_color_rgb_to_gray (CtxState *state, const 
 3561                                                      float *rgb)
 3562 {
 3563         // XXX todo replace with correct according to primaries
 3564   return CTX_CSS_RGB_TO_LUMINANCE(rgb);
 3565 }
 3566 CTX_INLINE static uint8_t ctx_u8_color_rgb_to_gray (CtxState *state, const 
 3567                                                     uint8_t *rgb)
 3568 {
 3569         // XXX todo replace with correct according to primaries
 3570   return CTX_CSS_RGB_TO_LUMINANCE(rgb);
 3571 }
 3572 
 3573 static void ctx_color_get_graya (CtxState *state, CtxColor *color, float 
 3574                                  *out)
 3575 {
 3576   if (! (color->valid & CTX_VALID_GRAYA) )
 3577     {
 3578       float rgba[4];
 3579       ctx_color_get_drgba (state, color, rgba);
 3580       color->l = ctx_float_color_rgb_to_gray (state, rgba);
 3581       color->valid |= CTX_VALID_GRAYA;
 3582     }
 3583   out[0] = color->l;
 3584   out[1] = color->alpha;
 3585 }
 3586 
 3587 #if CTX_ENABLE_CMYK
 3588 CTX_INLINE static void ctx_color_get_cmyka (CtxState *state, CtxColor 
 3589                                             *color, float *out)
 3590 {
 3591   if (! (color->valid & CTX_VALID_CMYKA) )
 3592     {
 3593       if (color->valid & CTX_VALID_GRAYA)
 3594         {
 3595           color->cyan = color->magenta = color->yellow = 0.0;
 3596           color->key = color->l;
 3597         }
 3598       else
 3599         {
 3600           float rgba[4];
 3601           ctx_color_get_rgba (state, color, rgba);
 3602           ctx_rgb_to_cmyk (rgba[0], rgba[1], rgba[2],
 3603                            &color->cyan, &color->magenta, &color->yellow, 
 3604                            &color->key);
 3605           color->alpha = rgba[3];
 3606         }
 3607       color->valid |= CTX_VALID_CMYKA;
 3608     }
 3609   out[0] = color->cyan;
 3610   out[1] = color->magenta;
 3611   out[2] = color->yellow;
 3612   out[3] = color->key;
 3613   out[4] = color->alpha;
 3614 }
 3615 
 3616 #if 0
 3617 static void ctx_color_get_cmyka_u8 (CtxState *state, CtxColor *color, 
 3618                                     uint8_t *out)
 3619 {
 3620   if (! (color->valid & CTX_VALID_CMYKA_U8) )
 3621     {
 3622       float cmyka[5];
 3623       ctx_color_get_cmyka (color, cmyka);
 3624       for (int i = 0; i < 5; i ++)
 3625         { color->cmyka[i] = ctx_float_to_u8 (cmyka[i]); }
 3626       color->valid |= CTX_VALID_CMYKA_U8;
 3627     }
 3628   out[0] = color->cmyka[0];
 3629   out[1] = color->cmyka[1];
 3630   out[2] = color->cmyka[2];
 3631   out[3] = color->cmyka[3];
 3632 }
 3633 #endif
 3634 #endif
 3635 
 3636 CTX_INLINE static void
 3637 ctx_color_get_rgba8 (CtxState *state, CtxColor *color, uint8_t *out)
 3638 {
 3639   if (! (color->valid & CTX_VALID_RGBA_U8) )
 3640     {
 3641       float rgba[4];
 3642       ctx_color_get_drgba (state, color, rgba);
 3643       for (int i = 0; i < 4; i ++)
 3644         { color->rgba[i] = ctx_float_to_u8 (rgba[i]); }
 3645       color->valid |= CTX_VALID_RGBA_U8;
 3646     }
 3647   out[0] = color->rgba[0];
 3648   out[1] = color->rgba[1];
 3649   out[2] = color->rgba[2];
 3650   out[3] = color->rgba[3];
 3651 }
 3652 
 3653 CTX_INLINE static void ctx_color_get_graya_u8 (CtxState *state, CtxColor 
 3654                                                *color, uint8_t *out)
 3655 {
 3656   if (! (color->valid & CTX_VALID_GRAYA_U8) )
 3657     {
 3658       float graya[2];
 3659       ctx_color_get_graya (state, color, graya);
 3660       color->l_u8 = ctx_float_to_u8 (graya[0]);
 3661       color->rgba[3] = ctx_float_to_u8 (graya[1]);
 3662       color->valid |= CTX_VALID_GRAYA_U8;
 3663     }
 3664   out[0] = color->l_u8;
 3665   out[1] = color->rgba[3];
 3666 }
 3667 
 3668 #if CTX_RASTERIZER
 3669 
 3670 typedef struct CtxEdge
 3671 {
 3672 #if CTX_BLOATY_FAST_PATHS
 3673   uint32_t index;  // provide for more aligned memory accesses.
 3674   uint32_t pad;    //
 3675 #else
 3676   uint16_t index;
 3677 #endif
 3678   int32_t  x;     /* the center-line intersection      */
 3679   int32_t  dx;
 3680 } CtxEdge;
 3681 
 3682 typedef void (*CtxFragment) (CtxRasterizer *rasterizer, float x, float y, 
 3683               void *out);
 3684 
 3685 #define CTX_MAX_GAUSSIAN_KERNEL_DIM    512
 3686 
 3687 struct _CtxRasterizer
 3688 {
 3689   CtxImplementation vfuncs;
 3690   /* these should be initialized and used as the bounds for rendering into 
 3691   the
 3692      buffer as well XXX: not yet in use, and when in use will only be
 3693      correct for axis aligned clips - proper rasterization of a clipping 
 3694      path
 3695      would be yet another refinement on top.
 3696    */
 3697 #if CTX_ENABLE_CLIP
 3698   CtxBuffer *clip_buffer;
 3699 #endif
 3700 
 3701 #if CTX_ENABLE_SHADOW_BLUR
 3702   float      kernel[CTX_MAX_GAUSSIAN_KERNEL_DIM];
 3703 #endif
 3704 
 3705   int        aa;          // level of vertical aa
 3706   int        force_aa;    // force full AA
 3707   int        active_edges;
 3708 #if CTX_RASTERIZER_FORCE_AA==0
 3709   int        pending_edges;   // this-scanline
 3710   int        ending_edges;    // count of edges ending this scanline
 3711 #endif
 3712   int        edge_pos;         // where we're at in iterating all edges
 3713   CtxEdge    edges[CTX_MAX_EDGES];
 3714 
 3715   int        scanline;
 3716   int        scan_min;
 3717   int        scan_max;
 3718   int        col_min;
 3719   int        col_max;
 3720 
 3721 #if CTX_BRAILLE_TEXT
 3722   CtxList   *glyphs;
 3723 #endif
 3724 
 3725   CtxRenderstream edge_list;
 3726 
 3727   CtxState  *state;
 3728   Ctx       *ctx;
 3729   Ctx       *texture_source; /* normally same as ctx */
 3730 
 3731   void      *buf;
 3732 
 3733 #if CTX_COMPOSITING_GROUPS
 3734   void      *saved_buf; // when group redirected
 3735   CtxBuffer *group[CTX_GROUP_MAX];
 3736 #endif
 3737 
 3738   float      x;  // < redundant? use state instead?
 3739   float      y;
 3740 
 3741   float      first_x;
 3742   float      first_y;
 3743   int8_t     needs_aa; // count of how many edges implies antialiasing
 3744   int        has_shape:2;
 3745   int        has_prev:2;
 3746   int        preserve:1;
 3747   int        uses_transforms:1;
 3748 #if CTX_BRAILLE_TEXT
 3749   int        term_glyphs:1; // store appropriate glyphs for redisplay
 3750 #endif
 3751 
 3752   int16_t    blit_x;
 3753   int16_t    blit_y;
 3754   int16_t    blit_width;
 3755   int16_t    blit_height;
 3756   int16_t    blit_stride;
 3757 
 3758   CtxPixelFormatInfo *format;
 3759 
 3760 #if CTX_ENABLE_SHADOW_BLUR
 3761   int in_shadow;
 3762 #endif
 3763   int in_text;
 3764   int shadow_x;
 3765   int shadow_y;
 3766 
 3767   CtxFragment         fragment;
 3768   uint8_t             color[4*5];
 3769 
 3770 #define CTX_COMPOSITE_ARGUMENTS CtxRasterizer *rasterizer, uint8_t * 
 3771 __restrict__ dst, uint8_t * __restrict__ src, int x0, uint8_t * 
 3772 __restrict__ coverage, int count
 3773 
 3774   void (*comp_op)(CTX_COMPOSITE_ARGUMENTS);
 3775 
 3776   uint8_t *clip_mask;
 3777 };
 3778 
 3779 typedef struct _CtxRectangle CtxRectangle;
 3780 struct _CtxRectangle {
 3781   int x;
 3782   int y;
 3783   int width;
 3784   int height;
 3785 };
 3786 
 3787 typedef struct _CtxHasher CtxHasher;
 3788 struct _CtxHasher
 3789 {
 3790   CtxRasterizer rasterizer;
 3791   int           cols;
 3792   int           rows;
 3793   uint32_t     *hashes;
 3794 };
 3795 
 3796 struct _CtxPixelFormatInfo
 3797 {
 3798   CtxPixelFormat pixel_format;
 3799   uint8_t        components:4; /* number of components */
 3800   uint8_t        bpp; /* bits  per pixel - for doing offset computations
 3801                          along with rowstride found elsewhere, if 0 it 
 3802                          indicates
 3803                          1/8  */
 3804   uint8_t        ebpp; /*effective bytes per pixel - for doing offset
 3805                          computations, for formats that get converted, the
 3806                          ebpp of the working space applied */
 3807   uint8_t        dither_red_blue;
 3808   uint8_t        dither_green;
 3809   CtxPixelFormat composite_format;
 3810 
 3811   void         (*to_comp) (CtxRasterizer *r,
 3812                            int x, const void * __restrict__ src, uint8_t * 
 3813                            __restrict__ comp, int count);
 3814   void         (*from_comp) (CtxRasterizer *r,
 3815                              int x, const uint8_t * __restrict__ comp, void 
 3816                              *__restrict__ dst, int count);
 3817   void         (*apply_coverage) (CtxRasterizer *r, uint8_t * __restrict__ 
 3818                 dst, uint8_t * __restrict__ src, int x, uint8_t *coverage,
 3819                           int count);
 3820   void         (*setup) (CtxRasterizer *r);
 3821 };
 3822 
 3823 #endif
 3824 
 3825 struct
 3826   _CtxIterator
 3827 {
 3828   int              pos;
 3829   int              in_history;
 3830   CtxRenderstream *renderstream;
 3831   int              end_pos;
 3832   int              flags;
 3833 
 3834   int              bitpack_pos;
 3835   int              bitpack_length;     // if non 0 bitpack is active
 3836   CtxEntry         bitpack_command[6]; // the command returned to the
 3837   // user if unpacking is needed.
 3838 };
 3839 
 3840 #define CTX_MAX_DEVICES 16
 3841 #define CTX_MAX_KEYBINDINGS         256
 3842 
 3843 #if CTX_EVENTS 
 3844 
 3845 // include list implementation - since it already is a header+inline online
 3846 // implementation?
 3847 
 3848 typedef struct CtxItemCb {
 3849   CtxEventType types;
 3850   CtxCb        cb;
 3851   void*        data1;
 3852   void*        data2;
 3853 
 3854   void (*finalize) (void *data1, void *data2, void *finalize_data);
 3855   void  *finalize_data;
 3856 
 3857 } CtxItemCb;
 3858 
 3859 
 3860 #define CTX_MAX_CBS              128
 3861 
 3862 typedef struct CtxItem {
 3863   CtxMatrix inv_matrix;  /* for event coordinate transforms */
 3864 
 3865   /* bounding box */
 3866   float          x0;
 3867   float          y0;
 3868   float          x1;
 3869   float          y1;
 3870 
 3871   void *path;
 3872   double          path_hash;
 3873 
 3874   CtxEventType   types;   /* all cb's ored together */
 3875   CtxItemCb cb[CTX_MAX_CBS];
 3876   int       cb_count;
 3877   int       ref_count;
 3878 } CtxItem;
 3879 
 3880 
 3881 typedef struct _CtxEvents CtxEvents;
 3882 struct _CtxEvents
 3883 {
 3884   int             frozen;
 3885   int             fullscreen;
 3886   CtxList        *grabs; /* could split the grabs per device in the same 
 3887   way,
 3888                             to make dispatch overhead smaller,. probably
 3889                             not much to win though. */
 3890   CtxItem         *prev[CTX_MAX_DEVICES];
 3891   float            pointer_x[CTX_MAX_DEVICES];
 3892   float            pointer_y[CTX_MAX_DEVICES];
 3893   unsigned char    pointer_down[CTX_MAX_DEVICES];
 3894   CtxEvent         drag_event[CTX_MAX_DEVICES];
 3895   CtxList         *idles;
 3896   CtxList         *events; // for ctx_get_event
 3897   int              ctx_get_event_enabled;
 3898   int              idle_id;
 3899   CtxBinding       bindings[CTX_MAX_KEYBINDINGS]; /*< better as list, uses 
 3900   no mem if unused */
 3901   int              n_bindings;
 3902   int              width;
 3903   int              height;
 3904   CtxList         *items;
 3905   CtxModifierState modifier_state;
 3906   int              tap_delay_min;
 3907   int              tap_delay_max;
 3908   int              tap_delay_hold;
 3909   double           tap_hysteresis;
 3910 };
 3911 
 3912 
 3913 #endif
 3914 
 3915 struct
 3916   _Ctx
 3917 {
 3918   CtxImplementation *renderer;
 3919   CtxRenderstream    renderstream;
 3920   CtxState           state;        /**/
 3921   int                transformation;
 3922   CtxBuffer          texture[CTX_MAX_TEXTURES];
 3923   int                rev;
 3924 #if CTX_EVENTS 
 3925   CtxEvents          events;
 3926   int                mouse_fd;
 3927   int                mouse_x;
 3928   int                mouse_y;
 3929 #endif
 3930 #if CTX_CURRENT_PATH
 3931   CtxRenderstream    current_path; // possibly transformed coordinates !
 3932   CtxIterator        current_path_iterator;
 3933 #endif
 3934 };
 3935 
 3936 #if CTX_EVENTS
 3937 int ctx_width (Ctx *ctx)
 3938 {
 3939   return ctx->events.width;
 3940 }
 3941 int ctx_height (Ctx *ctx)
 3942 {
 3943   return ctx->events.height;
 3944 }
 3945 
 3946 #endif
 3947 int ctx_rev (Ctx *ctx)
 3948 {
 3949   return ctx->rev;
 3950 }
 3951 
 3952 const char *ctx_get_string (Ctx *ctx, uint32_t hash)
 3953 {
 3954   return ctx_state_get_string (&ctx->state, hash);
 3955 }
 3956 float ctx_get_float (Ctx *ctx, uint32_t hash)
 3957 {
 3958   return ctx_state_get (&ctx->state, hash);
 3959 }
 3960 int ctx_get_int (Ctx *ctx, uint32_t hash)
 3961 {
 3962   return ctx_state_get (&ctx->state, hash);
 3963 }
 3964 void ctx_set_float (Ctx *ctx, uint32_t hash, float value)
 3965 {
 3966   ctx_state_set (&ctx->state, hash, value);
 3967 }
 3968 void ctx_set_string (Ctx *ctx, uint32_t hash, const char *value)
 3969 {
 3970   ctx_state_set_string (&ctx->state, hash, value);
 3971 }
 3972 void ctx_set_color (Ctx *ctx, uint32_t hash, CtxColor *color)
 3973 {
 3974   ctx_state_set_color (&ctx->state, hash, color);
 3975 }
 3976 int  ctx_get_color (Ctx *ctx, uint32_t hash, CtxColor *color)
 3977 {
 3978   return ctx_state_get_color (&ctx->state, hash, color);
 3979 }
 3980 int ctx_is_set (Ctx *ctx, uint32_t hash)
 3981 {
 3982   return ctx_get_float (ctx, hash) != -0.0f;
 3983 }
 3984 int ctx_is_set_now (Ctx *ctx, uint32_t hash)
 3985 {
 3986   return ctx_is_set (ctx, hash);
 3987 }
 3988 
 3989 typedef struct _CtxFont       CtxFont;
 3990 typedef struct _CtxFontEngine CtxFontEngine;
 3991 
 3992 struct _CtxFontEngine
 3993 {
 3994 #if CTX_FONTS_FROM_FILE
 3995   int   (*load_file)   (const char *name, const char *path);
 3996 #endif
 3997   int   (*load_memory) (const char *name, const void *data, int length);
 3998   int   (*glyph)       (CtxFont *font, Ctx *ctx, uint32_t unichar, int 
 3999          stroke);
 4000   float (*glyph_width) (CtxFont *font, Ctx *ctx, uint32_t unichar);
 4001   float (*glyph_kern)  (CtxFont *font, Ctx *ctx, uint32_t unicharA, 
 4002          uint32_t unicharB);
 4003 };
 4004 
 4005 struct _CtxFont
 4006 {
 4007   CtxFontEngine *engine;
 4008   const char *name;
 4009   int type; // 0 ctx    1 stb    2 monobitmap
 4010   union
 4011   {
 4012     struct
 4013     {
 4014       CtxEntry *data;
 4015       int length;
 4016       int first_kern;
 4017       /* we've got ~110 bytes to fill to cover as
 4018          much data as stbtt_fontinfo */
 4019       //int16_t glyph_pos[26]; // for a..z
 4020       int       glyphs; // number of glyphs
 4021       uint32_t *index;
 4022     } ctx;
 4023 #if CTX_FONT_ENGINE_STB
 4024     struct
 4025     {
 4026       stbtt_fontinfo ttf_info;
 4027       int cache_index;
 4028       int cache_unichar;
 4029     } stb;
 4030 #endif
 4031     struct { int start; int end; int gw; int gh; const uint8_t *data;} 
 4032              monobitmap;
 4033   };
 4034 };
 4035 
 4036 static CtxFont ctx_fonts[CTX_MAX_FONTS];
 4037 static int     ctx_font_count = 0;
 4038 
 4039 void ctx_dirty_rect (Ctx *ctx, int *x, int *y, int *width, int *height)
 4040 {
 4041   if ( (ctx->state.min_x > ctx->state.max_x) ||
 4042        (ctx->state.min_y > ctx->state.max_y) )
 4043     {
 4044       if (x) { *x = 0; }
 4045       if (y) { *y = 0; }
 4046       if (width) { *width = 0; }
 4047       if (height) { *height = 0; }
 4048       return;
 4049     }
 4050   if (ctx->state.min_x < 0)
 4051     { ctx->state.min_x = 0; }
 4052   if (ctx->state.min_y < 0)
 4053     { ctx->state.min_y = 0; }
 4054   if (x) { *x = ctx->state.min_x; }
 4055   if (y) { *y = ctx->state.min_y; }
 4056   if (width) { *width = ctx->state.max_x - ctx->state.min_x; }
 4057   if (height) { *height = ctx->state.max_y - ctx->state.min_y; }
 4058   //fprintf (stderr, "%i %i %ix%i\n", *x, *y, *width, *height);
 4059 }
 4060 
 4061 void ctx_process (Ctx *ctx, CtxEntry *entry);
 4062 
 4063 static void // XXX unused
 4064 ctx_matrix_set (CtxMatrix *matrix, float a, float b, float c, float d, 
 4065                 float e, float f)
 4066 {
 4067   matrix->m[0][0] = a;
 4068   matrix->m[0][1] = b;
 4069   matrix->m[1][0] = c;
 4070   matrix->m[1][1] = d;
 4071   matrix->m[2][0] = e;
 4072   matrix->m[2][1] = f;
 4073 }
 4074 
 4075 static void
 4076 ctx_matrix_identity (CtxMatrix *matrix)
 4077 {
 4078   matrix->m[0][0] = 1.0f;
 4079   matrix->m[0][1] = 0.0f;
 4080   matrix->m[1][0] = 0.0f;
 4081   matrix->m[1][1] = 1.0f;
 4082   matrix->m[2][0] = 0.0f;
 4083   matrix->m[2][1] = 0.0f;
 4084 }
 4085 
 4086 static void
 4087 ctx_matrix_multiply (CtxMatrix       *result,
 4088                      const CtxMatrix *t,
 4089                      const CtxMatrix *s)
 4090 {
 4091   CtxMatrix r;
 4092   r.m[0][0] = t->m[0][0] * s->m[0][0] + t->m[0][1] * s->m[1][0];
 4093   r.m[0][1] = t->m[0][0] * s->m[0][1] + t->m[0][1] * s->m[1][1];
 4094   r.m[1][0] = t->m[1][0] * s->m[0][0] + t->m[1][1] * s->m[1][0];
 4095   r.m[1][1] = t->m[1][0] * s->m[0][1] + t->m[1][1] * s->m[1][1];
 4096   r.m[2][0] = t->m[2][0] * s->m[0][0] + t->m[2][1] * s->m[1][0] + s->m[2][0]
 4097               ;
 4098   r.m[2][1] = t->m[2][0] * s->m[0][1] + t->m[2][1] * s->m[1][1] + s->m[2][1]
 4099               ;
 4100   *result = r;
 4101 }
 4102 
 4103 static void
 4104 ctx_matrix_translate (CtxMatrix *matrix, float x, float y)
 4105 {
 4106   CtxMatrix transform;
 4107   transform.m[0][0] = 1.0f;
 4108   transform.m[0][1] = 0.0f;
 4109   transform.m[1][0] = 0.0f;
 4110   transform.m[1][1] = 1.0f;
 4111   transform.m[2][0] = x;
 4112   transform.m[2][1] = y;
 4113   ctx_matrix_multiply (matrix, &transform, matrix);
 4114 }
 4115 
 4116 static void
 4117 ctx_matrix_scale (CtxMatrix *matrix, float x, float y)
 4118 {
 4119   CtxMatrix transform;
 4120   transform.m[0][0] = x;
 4121   transform.m[0][1] = 0.0f;
 4122   transform.m[1][0] = 0.0f;
 4123   transform.m[1][1] = y;
 4124   transform.m[2][0] = 0.0f;
 4125   transform.m[2][1] = 0.0f;
 4126   ctx_matrix_multiply (matrix, &transform, matrix);
 4127 }
 4128 
 4129 static void
 4130 ctx_matrix_rotate (CtxMatrix *matrix, float angle)
 4131 {
 4132   CtxMatrix transform;
 4133   float val_sin = ctx_sinf (angle);
 4134   float val_cos = ctx_cosf (angle);
 4135   transform.m[0][0] =  val_cos;
 4136   transform.m[0][1] = val_sin;
 4137   transform.m[1][0] = -val_sin;
 4138   transform.m[1][1] = val_cos;
 4139   transform.m[2][0] =     0.0f;
 4140   transform.m[2][1] = 0.0f;
 4141   ctx_matrix_multiply (matrix, &transform, matrix);
 4142 }
 4143 
 4144 #if 0
 4145 static void
 4146 ctx_matrix_skew_x (CtxMatrix *matrix, float angle)
 4147 {
 4148   CtxMatrix transform;
 4149   float val_tan = ctx_tanf (angle);
 4150   transform.m[0][0] =    1.0f;
 4151   transform.m[0][1] = 0.0f;
 4152   transform.m[1][0] = val_tan;
 4153   transform.m[1][1] = 1.0f;
 4154   transform.m[2][0] =    0.0f;
 4155   transform.m[2][1] = 0.0f;
 4156   ctx_matrix_multiply (matrix, &transform, matrix);
 4157 }
 4158 
 4159 static void
 4160 ctx_matrix_skew_y (CtxMatrix *matrix, float angle)
 4161 {
 4162   CtxMatrix transform;
 4163   float val_tan = ctx_tanf (angle);
 4164   transform.m[0][0] =    1.0f;
 4165   transform.m[0][1] = val_tan;
 4166   transform.m[1][0] =    0.0f;
 4167   transform.m[1][1] = 1.0f;
 4168   transform.m[2][0] =    0.0f;
 4169   transform.m[2][1] = 0.0f;
 4170   ctx_matrix_multiply (matrix, &transform, matrix);
 4171 }
 4172 #endif
 4173 
 4174 static int
 4175 ctx_conts_for_entry (CtxEntry *entry)
 4176 {
 4177     switch (entry->code)
 4178     {
 4179       case CTX_DATA:
 4180         return entry->data.u32[1];
 4181       case CTX_LINEAR_GRADIENT:
 4182         return 1;
 4183       case CTX_RADIAL_GRADIENT:
 4184       case CTX_ARC:
 4185       case CTX_ARC_TO:
 4186       case CTX_REL_ARC_TO:
 4187       case CTX_CURVE_TO:
 4188       case CTX_REL_CURVE_TO:
 4189       case CTX_APPLY_TRANSFORM:
 4190       case CTX_COLOR:
 4191       case CTX_ROUND_RECTANGLE:
 4192       case CTX_SHADOW_COLOR:
 4193         return 2;
 4194       case CTX_RECTANGLE:
 4195       case CTX_VIEW_BOX:
 4196       case CTX_REL_QUAD_TO:
 4197       case CTX_QUAD_TO:
 4198       case CTX_TEXTURE:
 4199         return 1;
 4200       default:
 4201         return 0;
 4202     }
 4203 }
 4204 
 4205 // expanding arc_to to arc can be the job
 4206 // of a layer in front of renderer?
 4207 //   doing:
 4208 //     rectangle
 4209 //     arc
 4210 //     ... etc reduction to beziers
 4211 //     or even do the reduction to
 4212 //     polylines directly here...
 4213 //     making the rasterizer able to
 4214 //     only do poly-lines? will that be faster?
 4215 
 4216 /* the iterator - should decode bitpacked data as well -
 4217  * making the rasterizers simpler, possibly do unpacking
 4218  * all the way to absolute coordinates.. unless mixed
 4219  * relative/not are wanted.
 4220  */
 4221 
 4222 enum _CtxIteratorFlag
 4223 {
 4224   CTX_ITERATOR_FLAT           = 0,
 4225   CTX_ITERATOR_EXPAND_BITPACK = 2,
 4226   CTX_ITERATOR_DEFAULTS       = CTX_ITERATOR_EXPAND_BITPACK
 4227 };
 4228 typedef enum _CtxIteratorFlag CtxIteratorFlag;
 4229 
 4230 static void
 4231 ctx_iterator_init (CtxIterator      *iterator,
 4232                    CtxRenderstream  *renderstream,
 4233                    int               start_pos,
 4234                    int               flags)
 4235 {
 4236   iterator->renderstream   = renderstream;
 4237   iterator->flags          = flags;
 4238   iterator->bitpack_pos    = 0;
 4239   iterator->bitpack_length = 0;
 4240   iterator->pos            = start_pos;
 4241   iterator->end_pos        = renderstream->count;
 4242   iterator->in_history     = -1; // -1 is a marker used for first run
 4243   ctx_memset (iterator->bitpack_command, 0, sizeof (iterator->
 4244               bitpack_command) );
 4245 }
 4246 
 4247 static CtxEntry *_ctx_iterator_next (CtxIterator *iterator)
 4248 {
 4249   int ret = iterator->pos;
 4250   CtxEntry *entry = &iterator->renderstream->entries[ret];
 4251   if (ret >= iterator->end_pos)
 4252     { return NULL; }
 4253   if (iterator->in_history == 0)
 4254     { iterator->pos += (ctx_conts_for_entry (entry) + 1); }
 4255   iterator->in_history = 0;
 4256   if (iterator->pos >= iterator->end_pos)
 4257     { return NULL; }
 4258   return &iterator->renderstream->entries[iterator->pos];
 4259 }
 4260 
 4261 #if CTX_CURRENT_PATH
 4262 CtxIterator *
 4263 ctx_current_path (Ctx *ctx)
 4264 {
 4265   CtxIterator *iterator = &ctx->current_path_iterator;
 4266   ctx_iterator_init (iterator, &ctx->current_path, 0, 
 4267                      CTX_ITERATOR_EXPAND_BITPACK);
 4268   return iterator;
 4269 }
 4270 
 4271 void
 4272 ctx_path_extents (Ctx *ctx, float *ex1, float *ey1, float *ex2, float *ey2)
 4273 {
 4274   float minx = 50000.0;
 4275   float miny = 50000.0;
 4276   float maxx = -50000.0;
 4277   float maxy = -50000.0;
 4278   float x = 0;
 4279   float y = 0;
 4280 
 4281   CtxIterator *iterator = ctx_current_path (ctx);
 4282   CtxCommand *command;
 4283 
 4284   while ((command = ctx_iterator_next (iterator)))
 4285   {
 4286      int got_coord = 0;
 4287      switch (command->code)
 4288      {
 4289         // XXX missing many curve types
 4290         case CTX_LINE_TO:
 4291         case CTX_MOVE_TO:
 4292           x = command->move_to.x;
 4293           y = command->move_to.y;
 4294           got_coord++;
 4295           break;
 4296         case CTX_REL_LINE_TO:
 4297         case CTX_REL_MOVE_TO:
 4298           x += command->move_to.x;
 4299           y += command->move_to.y;
 4300           got_coord++;
 4301           break;
 4302         case CTX_CURVE_TO:
 4303           x = command->curve_to.x;
 4304           y = command->curve_to.y;
 4305           got_coord++;
 4306           break;
 4307         case CTX_REL_CURVE_TO:
 4308           x += command->curve_to.x;
 4309           y += command->curve_to.y;
 4310           got_coord++;
 4311           break;
 4312         case CTX_RECTANGLE:
 4313         case CTX_ROUND_RECTANGLE:
 4314           x = command->rectangle.x;
 4315           y = command->rectangle.y;
 4316           minx = ctx_minf (minx, x);
 4317           miny = ctx_minf (miny, y);
 4318           maxx = ctx_maxf (maxx, x);
 4319           maxy = ctx_maxf (maxy, y);
 4320 
 4321           x += command->rectangle.width;
 4322           y += command->rectangle.height;
 4323           got_coord++;
 4324           break;
 4325      }
 4326     if (got_coord)
 4327     {
 4328       minx = ctx_minf (minx, x);
 4329       miny = ctx_minf (miny, y);
 4330       maxx = ctx_maxf (maxx, x);
 4331       maxy = ctx_maxf (maxy, y);
 4332     }
 4333   }
 4334   if (ex1) *ex1 = minx;
 4335   if (ey1) *ey1 = miny;
 4336   if (ex2) *ex2 = maxx;
 4337   if (ey2) *ey2 = maxy;
 4338 }
 4339 
 4340 
 4341 #endif
 4342 // 6024x4008
 4343 #if CTX_BITPACK
 4344 static void
 4345 ctx_iterator_expand_s8_args (CtxIterator *iterator, CtxEntry *entry)
 4346 {
 4347   int no = 0;
 4348   for (int cno = 0; cno < 4; cno++)
 4349     for (int d = 0; d < 2; d++, no++)
 4350       iterator->bitpack_command[cno].data.f[d] =
 4351         entry->data.s8[no] * 1.0f / CTX_SUBDIV;
 4352   iterator->bitpack_command[0].code =
 4353     iterator->bitpack_command[1].code =
 4354       iterator->bitpack_command[2].code =
 4355         iterator->bitpack_command[3].code = CTX_CONT;
 4356   iterator->bitpack_length = 4;
 4357   iterator->bitpack_pos = 0;
 4358 }
 4359 
 4360 static void
 4361 ctx_iterator_expand_s16_args (CtxIterator *iterator, CtxEntry *entry)
 4362 {
 4363   int no = 0;
 4364   for (int cno = 0; cno < 2; cno++)
 4365     for (int d = 0; d < 2; d++, no++)
 4366       iterator->bitpack_command[cno].data.f[d] = entry->data.s16[no] * 1.0f 
 4367                                                  /
 4368           CTX_SUBDIV;
 4369   iterator->bitpack_command[0].code =
 4370     iterator->bitpack_command[1].code = CTX_CONT;
 4371   iterator->bitpack_length = 2;
 4372   iterator->bitpack_pos    = 0;
 4373 }
 4374 #endif
 4375 
 4376 CtxCommand *
 4377 ctx_iterator_next (CtxIterator *iterator)
 4378 {
 4379   CtxEntry *ret;
 4380 #if CTX_BITPACK
 4381   int expand_bitpack = iterator->flags & CTX_ITERATOR_EXPAND_BITPACK;
 4382 again:
 4383   if (iterator->bitpack_length)
 4384     {
 4385       ret = &iterator->bitpack_command[iterator->bitpack_pos];
 4386       iterator->bitpack_pos += (ctx_conts_for_entry (ret) + 1);
 4387       if (iterator->bitpack_pos >= iterator->bitpack_length)
 4388         {
 4389           iterator->bitpack_length = 0;
 4390         }
 4391       return (CtxCommand *) ret;
 4392     }
 4393 #endif
 4394   ret = _ctx_iterator_next (iterator);
 4395 #if CTX_BITPACK
 4396   if (ret && expand_bitpack)
 4397     switch (ret->code)
 4398       {
 4399         case CTX_REL_CURVE_TO_REL_LINE_TO:
 4400           ctx_iterator_expand_s8_args (iterator, ret);
 4401           iterator->bitpack_command[0].code = CTX_REL_CURVE_TO;
 4402           iterator->bitpack_command[1].code =
 4403           iterator->bitpack_command[2].code = CTX_CONT;
 4404           iterator->bitpack_command[3].code = CTX_REL_LINE_TO;
 4405           // 0.0 here is a common optimization - so check for it
 4406           if (ret->data.s8[6]== 0 && ret->data.s8[7] == 0)
 4407             { iterator->bitpack_length = 3; }
 4408           goto again;
 4409         case CTX_REL_LINE_TO_REL_CURVE_TO:
 4410           ctx_iterator_expand_s8_args (iterator, ret);
 4411           iterator->bitpack_command[0].code = CTX_REL_LINE_TO;
 4412           iterator->bitpack_command[1].code = CTX_REL_CURVE_TO;
 4413           goto again;
 4414         case CTX_REL_CURVE_TO_REL_MOVE_TO:
 4415           ctx_iterator_expand_s8_args (iterator, ret);
 4416           iterator->bitpack_command[0].code = CTX_REL_CURVE_TO;
 4417           iterator->bitpack_command[3].code = CTX_REL_MOVE_TO;
 4418           goto again;
 4419         case CTX_REL_LINE_TO_X4:
 4420           ctx_iterator_expand_s8_args (iterator, ret);
 4421           iterator->bitpack_command[0].code =
 4422           iterator->bitpack_command[1].code =
 4423           iterator->bitpack_command[2].code =
 4424           iterator->bitpack_command[3].code = CTX_REL_LINE_TO;
 4425           goto again;
 4426         case CTX_REL_QUAD_TO_S16:
 4427           ctx_iterator_expand_s16_args (iterator, ret);
 4428           iterator->bitpack_command[0].code = CTX_REL_QUAD_TO;
 4429           goto again;
 4430         case CTX_REL_QUAD_TO_REL_QUAD_TO:
 4431           ctx_iterator_expand_s8_args (iterator, ret);
 4432           iterator->bitpack_command[0].code =
 4433           iterator->bitpack_command[2].code = CTX_REL_QUAD_TO;
 4434           goto again;
 4435         case CTX_REL_LINE_TO_X2:
 4436           ctx_iterator_expand_s16_args (iterator, ret);
 4437           iterator->bitpack_command[0].code =
 4438           iterator->bitpack_command[1].code = CTX_REL_LINE_TO;
 4439           goto again;
 4440         case CTX_REL_LINE_TO_REL_MOVE_TO:
 4441           ctx_iterator_expand_s16_args (iterator, ret);
 4442           iterator->bitpack_command[0].code = CTX_REL_LINE_TO;
 4443           iterator->bitpack_command[1].code = CTX_REL_MOVE_TO;
 4444           goto again;
 4445         case CTX_MOVE_TO_REL_LINE_TO:
 4446           ctx_iterator_expand_s16_args (iterator, ret);
 4447           iterator->bitpack_command[0].code = CTX_MOVE_TO;
 4448           iterator->bitpack_command[1].code = CTX_REL_MOVE_TO;
 4449           goto again;
 4450         case CTX_FILL_MOVE_TO:
 4451           iterator->bitpack_command[1] = *ret;
 4452           iterator->bitpack_command[0].code = CTX_FILL;
 4453           iterator->bitpack_command[1].code = CTX_MOVE_TO;
 4454           iterator->bitpack_pos = 0;
 4455           iterator->bitpack_length = 2;
 4456           goto again;
 4457         case CTX_LINEAR_GRADIENT:
 4458         case CTX_QUAD_TO:
 4459         case CTX_REL_QUAD_TO:
 4460         case CTX_TEXTURE:
 4461         case CTX_RECTANGLE:
 4462         case CTX_VIEW_BOX:
 4463           iterator->bitpack_command[0] = ret[0];
 4464           iterator->bitpack_command[1] = ret[1];
 4465           iterator->bitpack_pos = 0;
 4466           iterator->bitpack_length = 2;
 4467           goto again;
 4468         case CTX_ARC:
 4469         case CTX_ARC_TO:
 4470         case CTX_REL_ARC_TO:
 4471         case CTX_COLOR:
 4472         case CTX_SHADOW_COLOR:
 4473         case CTX_RADIAL_GRADIENT:
 4474         case CTX_CURVE_TO:
 4475         case CTX_REL_CURVE_TO:
 4476         case CTX_APPLY_TRANSFORM:
 4477         case CTX_ROUND_RECTANGLE:
 4478           iterator->bitpack_command[0] = ret[0];
 4479           iterator->bitpack_command[1] = ret[1];
 4480           iterator->bitpack_command[2] = ret[2];
 4481           iterator->bitpack_pos = 0;
 4482           iterator->bitpack_length = 3;
 4483           goto again;
 4484         case CTX_TEXT:
 4485         case CTX_TEXT_STROKE:
 4486         case CTX_FONT:
 4487         case CTX_SET:
 4488           iterator->bitpack_length = 0;
 4489           return (CtxCommand *) ret;
 4490         default:
 4491           iterator->bitpack_command[0] = ret[0];
 4492           iterator->bitpack_command[1] = ret[1];
 4493           iterator->bitpack_command[2] = ret[2];
 4494           iterator->bitpack_command[3] = ret[3];
 4495           iterator->bitpack_command[4] = ret[4];
 4496           iterator->bitpack_pos = 0;
 4497           iterator->bitpack_length = 1;
 4498           goto again;
 4499       }
 4500 #endif
 4501   return (CtxCommand *) ret;
 4502 }
 4503 
 4504 static void
 4505 ctx_gstate_push (CtxState *state)
 4506 {
 4507   if (state->gstate_no + 1 >= CTX_MAX_STATES)
 4508     { return; }
 4509   state->gstate_stack[state->gstate_no] = state->gstate;
 4510   state->gstate_no++;
 4511   ctx_state_set (state, CTX_new_state, 0.0);
 4512   state->has_clipped=0;
 4513 }
 4514 
 4515 static void
 4516 ctx_gstate_pop (CtxState *state)
 4517 {
 4518   if (state->gstate_no <= 0)
 4519     { return; }
 4520   state->gstate = state->gstate_stack[state->gstate_no-1];
 4521   state->gstate_no--;
 4522 }
 4523 
 4524 static void ctx_interpret_style         (CtxState *state, CtxEntry *entry, 
 4525                                          void *data);
 4526 static void ctx_interpret_transforms    (CtxState *state, CtxEntry *entry, 
 4527                                          void *data);
 4528 static void ctx_interpret_pos           (CtxState *state, CtxEntry *entry, 
 4529                                          void *data);
 4530 static void ctx_interpret_pos_transform (CtxState *state, CtxEntry *entry, 
 4531                                          void *data);
 4532 
 4533 
 4534 static void ctx_renderstream_compact (CtxRenderstream *renderstream);
 4535 static void
 4536 ctx_renderstream_resize (CtxRenderstream *renderstream, int desired_size)
 4537 {
 4538 #if CTX_RENDERSTREAM_STATIC
 4539   if (renderstream->flags & CTX_RENDERSTREAM_EDGE_LIST)
 4540     {
 4541       static CtxEntry sbuf[CTX_MAX_EDGE_LIST_SIZE];
 4542       renderstream->entries = &sbuf[0];
 4543       renderstream->size = CTX_MAX_EDGE_LIST_SIZE;
 4544     }
 4545   else if (renderstream->flags & CTX_RENDERSTREAM_CURRENT_PATH)
 4546     {
 4547       static CtxEntry sbuf[CTX_MAX_EDGE_LIST_SIZE];
 4548       renderstream->entries = &sbuf[0];
 4549       renderstream->size = CTX_MAX_EDGE_LIST_SIZE;
 4550     }
 4551   else
 4552     {
 4553       static CtxEntry sbuf[CTX_MAX_JOURNAL_SIZE];
 4554       renderstream->entries = &sbuf[0];
 4555       renderstream->size = CTX_MAX_JOURNAL_SIZE;
 4556       ctx_renderstream_compact (renderstream);
 4557     }
 4558 #else
 4559   int new_size = desired_size;
 4560   int min_size = CTX_MIN_JOURNAL_SIZE;
 4561   int max_size = CTX_MAX_JOURNAL_SIZE;
 4562   if (renderstream->flags & CTX_RENDERSTREAM_EDGE_LIST)
 4563     {
 4564       min_size = CTX_MIN_EDGE_LIST_SIZE;
 4565       max_size = CTX_MAX_EDGE_LIST_SIZE;
 4566     }
 4567   else if (renderstream->flags & CTX_RENDERSTREAM_CURRENT_PATH)
 4568     {
 4569       min_size = CTX_MIN_EDGE_LIST_SIZE;
 4570       max_size = CTX_MAX_EDGE_LIST_SIZE;
 4571     }
 4572   else
 4573     {
 4574       ctx_renderstream_compact (renderstream);
 4575     }
 4576   if (new_size < renderstream->size)
 4577     { return; }
 4578   if (renderstream->size == max_size)
 4579     { return; }
 4580   if (new_size < min_size)
 4581     { new_size = min_size; }
 4582   if (new_size < renderstream->count)
 4583     { new_size = renderstream->count + 4; }
 4584   if (new_size >= max_size)
 4585     { new_size = max_size; }
 4586   if (new_size != min_size)
 4587     {
 4588       //ctx_log ("growing renderstream %p to %d\n", renderstream, new_size);
 4589     }
 4590   if (renderstream->entries)
 4591     {
 4592       //printf ("grow %p to %d from %d\n", renderstream, new_size, 
 4593                 renderstream->size);
 4594       CtxEntry *ne =  (CtxEntry *) malloc (sizeof (CtxEntry) * new_size);
 4595       memcpy (ne, renderstream->entries, renderstream->size * sizeof (
 4596               CtxEntry) );
 4597       free (renderstream->entries);
 4598       renderstream->entries = ne;
 4599       //renderstream->entries = (CtxEntry*)malloc (renderstream->entries, 
 4600                                 sizeof (CtxEntry) * new_size);
 4601     }
 4602   else
 4603     {
 4604       //printf ("allocating for %p %d\n", renderstream, new_size);
 4605       renderstream->entries = (CtxEntry *) malloc (sizeof (CtxEntry) * 
 4606                               new_size);
 4607     }
 4608   renderstream->size = new_size;
 4609   //printf ("renderstream %p is %d\n", renderstream, renderstream->size);
 4610 #endif
 4611 }
 4612 
 4613 static int
 4614 ctx_renderstream_add_single (CtxRenderstream *renderstream, CtxEntry *entry)
 4615 {
 4616   int max_size = CTX_MAX_JOURNAL_SIZE;
 4617   int ret = renderstream->count;
 4618   if (renderstream->flags & CTX_RENDERSTREAM_EDGE_LIST)
 4619     {
 4620       max_size = CTX_MAX_EDGE_LIST_SIZE;
 4621     }
 4622   else if (renderstream->flags & CTX_RENDERSTREAM_CURRENT_PATH)
 4623     {
 4624       max_size = CTX_MAX_EDGE_LIST_SIZE;
 4625     }
 4626   if (renderstream->flags & CTX_RENDERSTREAM_DOESNT_OWN_ENTRIES)
 4627     {
 4628       return ret;
 4629     }
 4630   if (ret + 8 >= renderstream->size - 20)
 4631     {
 4632       ctx_renderstream_resize (renderstream, renderstream->size * 2);
 4633     }
 4634   if (renderstream->count >= max_size - 20)
 4635     {
 4636       return 0;
 4637     }
 4638   renderstream->entries[renderstream->count] = *entry;
 4639   ret = renderstream->count;
 4640   renderstream->count++;
 4641   return ret;
 4642 }
 4643 
 4644 int
 4645 ctx_add_single (Ctx *ctx, void *entry)
 4646 {
 4647   return ctx_renderstream_add_single (&ctx->renderstream, (CtxEntry *) 
 4648                                       entry);
 4649 }
 4650 
 4651 int
 4652 ctx_renderstream_add_entry (CtxRenderstream *renderstream, CtxEntry *entry)
 4653 {
 4654   int length = ctx_conts_for_entry (entry) + 1;
 4655   int ret = 0;
 4656   for (int i = 0; i < length; i ++)
 4657     {
 4658       ret = ctx_renderstream_add_single (renderstream, &entry[i]);
 4659     }
 4660   return ret;
 4661 }
 4662 
 4663 int ctx_append_renderstream (Ctx *ctx, void *data, int length)
 4664 {
 4665   CtxEntry *entries = (CtxEntry *) data;
 4666   if (length % sizeof (CtxEntry) )
 4667     {
 4668       //ctx_log("err\n");
 4669       return -1;
 4670     }
 4671   for (unsigned int i = 0; i < length / sizeof (CtxEntry); i++)
 4672     {
 4673       ctx_renderstream_add_single (&ctx->renderstream, &entries[i]);
 4674     }
 4675   return 0;
 4676 }
 4677 
 4678 int ctx_set_renderstream (Ctx *ctx, void *data, int length)
 4679 {
 4680   ctx->renderstream.count = 0;
 4681   ctx_append_renderstream (ctx, data, length);
 4682   return 0;
 4683 }
 4684 
 4685 int ctx_get_renderstream_count (Ctx *ctx)
 4686 {
 4687   return ctx->renderstream.count;
 4688 }
 4689 
 4690 int
 4691 ctx_add_data (Ctx *ctx, void *data, int length)
 4692 {
 4693   if (length % sizeof (CtxEntry) )
 4694     {
 4695       //ctx_log("err\n");
 4696       return -1;
 4697     }
 4698   /* some more input verification might be in order.. like
 4699    * verify that it is well-formed up to length?
 4700    *
 4701    * also - it would be very useful to stop processing
 4702    * upon flush - and do renderstream resizing.
 4703    */
 4704   return ctx_renderstream_add_entry (&ctx->renderstream, (CtxEntry *) data);
 4705 }
 4706 
 4707 static int ctx_renderstream_add_u32 (CtxRenderstream *renderstream, CtxCode 
 4708                                      code, uint32_t u32[2])
 4709 {
 4710   CtxEntry entry = {code, {{0},}};
 4711   entry.data.u32[0] = u32[0];
 4712   entry.data.u32[1] = u32[1];
 4713   return ctx_renderstream_add_single (renderstream, &entry);
 4714 }
 4715 
 4716 int ctx_renderstream_add_data (CtxRenderstream *renderstream, const void 
 4717                                *data, int length)
 4718 {
 4719   CtxEntry entry = {CTX_DATA, {{0},}};
 4720   entry.data.u32[0] = 0;
 4721   entry.data.u32[1] = 0;
 4722   int ret = ctx_renderstream_add_single (renderstream, &entry);
 4723   if (!data) { return -1; }
 4724   int length_in_blocks;
 4725   if (length <= 0) { length = strlen ( (char *) data) + 1; }
 4726   length_in_blocks = length / sizeof (CtxEntry);
 4727   length_in_blocks += (length % sizeof (CtxEntry) ) ?1:0;
 4728   if (renderstream->count + length_in_blocks + 4 > renderstream->size)
 4729     { ctx_renderstream_resize (renderstream, renderstream->count * 1.2 + 
 4730       length_in_blocks + 32); }
 4731   if (renderstream->count >= renderstream->size)
 4732     { return -1; }
 4733   renderstream->count += length_in_blocks;
 4734   renderstream->entries[ret].data.u32[0] = length;
 4735   renderstream->entries[ret].data.u32[1] = length_in_blocks;
 4736   memcpy (&renderstream->entries[ret+1], data, length);
 4737   {
 4738     //int reverse = ctx_renderstream_add (renderstream, CTX_DATA_REV);
 4739     CtxEntry entry = {CTX_DATA_REV, {{0},}};
 4740     entry.data.u32[0] = length;
 4741     entry.data.u32[1] = length_in_blocks;
 4742     ctx_renderstream_add_single (renderstream, &entry);
 4743     /* this reverse marker exist to enable more efficient
 4744        front to back traversal, can be ignored in other
 4745        direction, is this needed after string setters as well?
 4746      */
 4747   }
 4748   return ret;
 4749 }
 4750 
 4751 static CtxEntry
 4752 ctx_void (CtxCode code)
 4753 {
 4754   CtxEntry command;
 4755   command.code = code;
 4756   command.data.u32[0] = 0;
 4757   command.data.u32[1] = 0;
 4758   return command;
 4759 }
 4760 
 4761 static CtxEntry
 4762 ctx_f (CtxCode code, float x, float y)
 4763 {
 4764   CtxEntry command = ctx_void (code);
 4765   command.data.f[0] = x;
 4766   command.data.f[1] = y;
 4767   return command;
 4768 }
 4769 
 4770 static CtxEntry
 4771 ctx_u32 (CtxCode code, uint32_t x, uint32_t y)
 4772 {
 4773   CtxEntry command = ctx_void (code);
 4774   command.data.u32[0] = x;
 4775   command.data.u32[1] = y;
 4776   return command;
 4777 }
 4778 
 4779 #if 0
 4780 static CtxEntry
 4781 ctx_s32 (CtxCode code, int32_t x, int32_t y)
 4782 {
 4783   CtxEntry command = ctx_void (code);
 4784   command.data.s32[0] = x;
 4785   command.data.s32[1] = y;
 4786   return command;
 4787 }
 4788 #endif
 4789 
 4790 inline static CtxEntry
 4791 ctx_s16 (CtxCode code, int x0, int y0, int x1, int y1)
 4792 {
 4793   CtxEntry command = ctx_void (code);
 4794   command.data.s16[0] = x0;
 4795   command.data.s16[1] = y0;
 4796   command.data.s16[2] = x1;
 4797   command.data.s16[3] = y1;
 4798   return command;
 4799 }
 4800 
 4801 static CtxEntry
 4802 ctx_u8 (CtxCode code,
 4803         uint8_t a, uint8_t b, uint8_t c, uint8_t d,
 4804         uint8_t e, uint8_t f, uint8_t g, uint8_t h)
 4805 {
 4806   CtxEntry command = ctx_void (code);
 4807   command.data.u8[0] = a;
 4808   command.data.u8[1] = b;
 4809   command.data.u8[2] = c;
 4810   command.data.u8[3] = d;
 4811   command.data.u8[4] = e;
 4812   command.data.u8[5] = f;
 4813   command.data.u8[6] = g;
 4814   command.data.u8[7] = h;
 4815   return command;
 4816 }
 4817 
 4818 #define CTX_PROCESS_VOID(cmd) do {\
 4819   CtxEntry command = ctx_void (cmd); \
 4820   ctx_process (ctx, &command);}while(0) \
 4821 
 4822 #define CTX_PROCESS_F(cmd, x, y) do {\
 4823   CtxEntry command = ctx_f(cmd, x, y);\
 4824   ctx_process (ctx, &command);}while(0)
 4825 
 4826 #define CTX_PROCESS_F1(cmd, x) do {\
 4827   CtxEntry command = ctx_f(cmd, x, 0);\
 4828   ctx_process (ctx, &command);}while(0)
 4829 
 4830 #define CTX_PROCESS_U32(cmd, x, y) do {\
 4831   CtxEntry command = ctx_u32(cmd, x, y);\
 4832   ctx_process (ctx, &command);}while(0)
 4833 
 4834 #define CTX_PROCESS_U8(cmd, x) do {\
 4835   CtxEntry command = ctx_u8(cmd, x,0,0,0,0,0,0,0);\
 4836   ctx_process (ctx, &command);}while(0)
 4837 
 4838 
 4839 static void
 4840 ctx_process_cmd_str_with_len (Ctx *ctx, CtxCode code, const char *string, 
 4841                               uint32_t arg0, uint32_t arg1, int len)
 4842 {
 4843   CtxEntry commands[1 + 2 + len/8];
 4844   ctx_memset (commands, 0, sizeof (commands) );
 4845   commands[0] = ctx_u32 (code, arg0, arg1);
 4846   commands[1].code = CTX_DATA;
 4847   commands[1].data.u32[0] = len;
 4848   commands[1].data.u32[1] = len/9+1;
 4849   memcpy( (char *) &commands[2].data.u8[0], string, len);
 4850   ( (char *) (&commands[2].data.u8[0]) ) [len]=0;
 4851   ctx_process (ctx, commands);
 4852 }
 4853 
 4854 static void
 4855 ctx_process_cmd_str (Ctx *ctx, CtxCode code, const char *string, uint32_t 
 4856                      arg0, uint32_t arg1)
 4857 {
 4858   ctx_process_cmd_str_with_len (ctx, code, string, arg0, arg1, strlen (
 4859                                 string));
 4860 }
 4861 
 4862 void
 4863 ctx_close_path (Ctx *ctx)
 4864 {
 4865   CTX_PROCESS_VOID (CTX_CLOSE_PATH);
 4866 }
 4867 
 4868 void
 4869 ctx_get_rgba (Ctx *ctx, float *rgba)
 4870 {
 4871   ctx_color_get_rgba (& (ctx->state), &ctx->state.gstate.source.color, rgba)
 4872                       ;
 4873 }
 4874 
 4875 void
 4876 ctx_get_drgba (Ctx *ctx, float *rgba)
 4877 {
 4878   ctx_color_get_drgba (& (ctx->state), &ctx->state.gstate.source.color, 
 4879                        rgba);
 4880 }
 4881 
 4882 int ctx_in_fill (Ctx *ctx, float x, float y)
 4883 {
 4884   float x1, y1, x2, y2;
 4885   ctx_path_extents (ctx, &x1, &y1, &x2, &y2);
 4886 
 4887   if (x1 <= x && x <= x2 && // XXX - just bounding box for now
 4888       y1 <= y && y <= y2)   //
 4889     return 1;
 4890   return 0;
 4891 }
 4892 
 4893 uint8_t *
 4894 ctx_get_image_data (Ctx *ctx, int sx, int sy, int sw, int sh, int format, 
 4895                     int stride)
 4896 {
 4897    // NYI
 4898    return NULL;
 4899 }
 4900 
 4901 void
 4902 ctx_put_image_data (Ctx *ctx, uint8_t *data, int w, int h, int format, int 
 4903                     stride,
 4904                     int dx, int dy, int dirtyX, int dirtyY,
 4905                     int dirtyWidth, int dirtyHeight)
 4906 {
 4907    // NYI
 4908 }
 4909                     
 4910 
 4911 #if CTX_ENABLE_CMYK
 4912 void
 4913 ctx_get_cmyka (Ctx *ctx, float *cmyka)
 4914 {
 4915   ctx_color_get_cmyka (& (ctx->state), &ctx->state.gstate.source.color, 
 4916                        cmyka);
 4917 }
 4918 #endif
 4919 void
 4920 ctx_get_graya (Ctx *ctx, float *ya)
 4921 {
 4922   ctx_color_get_graya (& (ctx->state), &ctx->state.gstate.source.color, ya);
 4923 }
 4924 
 4925 #if CTX_ENABLE_CM
 4926 void
 4927 ctx_set_drgb_space (Ctx *ctx, int device_space)
 4928 {
 4929   CTX_PROCESS_U8 (CTX_SET_DRGB_SPACE, device_space);
 4930 }
 4931 
 4932 void
 4933 ctx_set_dcmyk_space (Ctx *ctx, int device_space)
 4934 {
 4935   CTX_PROCESS_U8 (CTX_SET_DCMYK_SPACE, device_space);
 4936 }
 4937 
 4938 void
 4939 ctx_rgb_space (Ctx *ctx, int device_space)
 4940 {
 4941   CTX_PROCESS_U8 (CTX_SET_RGB_SPACE, device_space);
 4942 }
 4943 
 4944 void
 4945 ctx_set_cmyk_space (Ctx *ctx, int device_space)
 4946 {
 4947   CTX_PROCESS_U8 (CTX_SET_CMYK_SPACE, device_space);
 4948 }
 4949 #endif
 4950 
 4951 void ctx_texture (Ctx *ctx, int id, float x, float y)
 4952 {
 4953   CtxEntry commands[2];
 4954   if (id < 0) { return; }
 4955   commands[0] = ctx_u32 (CTX_TEXTURE, id, 0);
 4956   commands[1] = ctx_f  (CTX_CONT, x, y);
 4957   ctx_process (ctx, commands);
 4958 }
 4959 
 4960 void
 4961 ctx_image_path (Ctx *ctx, const char *path, float x, float y)
 4962 {
 4963   int id = ctx_texture_load (ctx, -1, path);
 4964   ctx_texture (ctx, id, x, y);
 4965 
 4966   // query if image exists .. 
 4967   //   if it doesnt load, decode, encode, upload to path/
 4968 }
 4969 
 4970 void
 4971 ctx_rgba8 (Ctx *ctx, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
 4972 {
 4973   CtxEntry command = ctx_u8 (CTX_SET_RGBA_U8, r, g, b, a, 0, 0, 0, 0);
 4974 
 4975   uint8_t rgba[4];
 4976   ctx_color_get_rgba8 (&ctx->state, &ctx->state.gstate.source.color, rgba);
 4977   if (rgba[0] == r && rgba[1] == g && rgba[2] == b && rgba[3] == a)
 4978      return;
 4979 
 4980   ctx_process (ctx, &command);
 4981 }
 4982 
 4983 void
 4984 ctx_set_pixel_u8 (Ctx *ctx, uint16_t x, uint16_t y, uint8_t r, uint8_t g, 
 4985                   uint8_t b, uint8_t a)
 4986 {
 4987   CtxEntry command = ctx_u8 (CTX_SET_PIXEL, r, g, b, a, 0, 0, 0, 0);
 4988   command.data.u16[2]=x;
 4989   command.data.u16[3]=y;
 4990   ctx_process (ctx, &command);
 4991 }
 4992 
 4993 void ctx_drgba (Ctx *ctx, float r, float g, float b, float a)
 4994 {
 4995   CtxEntry command[3]=
 4996   {
 4997     ctx_f (CTX_COLOR, CTX_DRGBA, r),
 4998     ctx_f (CTX_CONT, g, b),
 4999     ctx_f (CTX_CONT, a, 0)
 5000   };
 5001   ctx_process (ctx, command);
 5002 }
 5003 
 5004 void ctx_rgba (Ctx *ctx, float r, float g, float b, float a)
 5005 {
 5006   CtxEntry command[3]=
 5007   {
 5008     ctx_f (CTX_COLOR, CTX_RGBA, r),
 5009     ctx_f (CTX_CONT, g, b),
 5010     ctx_f (CTX_CONT, a, 0)
 5011   };
 5012   float rgba[4];
 5013   ctx_color_get_rgba (&ctx->state, &ctx->state.gstate.source.color, rgba);
 5014   if (rgba[0] == r && rgba[1] == g && rgba[2] == b && rgba[3] == a)
 5015      return;
 5016   ctx_process (ctx, command);
 5017 }
 5018 
 5019 void ctx_rgb (Ctx *ctx, float   r, float   g, float   b)
 5020 {
 5021   ctx_rgba (ctx, r, g, b, 1.0f);
 5022 }
 5023 
 5024 void ctx_gray (Ctx *ctx, float gray)
 5025 {
 5026   CtxEntry command[3]=
 5027   {
 5028     ctx_f (CTX_COLOR, CTX_GRAY, gray),
 5029     ctx_f (CTX_CONT, 1.0f, 0.0f),
 5030     ctx_f (CTX_CONT, 0.0f, 0.0f)
 5031   };
 5032   ctx_process (ctx, command);
 5033 }
 5034 
 5035 #if CTX_ENABLE_CMYK
 5036 void ctx_cmyk (Ctx *ctx, float c, float m, float y, float k)
 5037 {
 5038   CtxEntry command[3]=
 5039   {
 5040     ctx_f (CTX_COLOR, CTX_CMYKA, c),
 5041     ctx_f (CTX_CONT, m, y),
 5042     ctx_f (CTX_CONT, k, 1.0f)
 5043   };
 5044   ctx_process (ctx, command);
 5045 }
 5046 
 5047 void ctx_cmyka      (Ctx *ctx, float c, float m, float y, float k, float a)
 5048 {
 5049   CtxEntry command[3]=
 5050   {
 5051     ctx_f (CTX_COLOR, CTX_CMYKA, c),
 5052     ctx_f (CTX_CONT, m, y),
 5053     ctx_f (CTX_CONT, k, a)
 5054   };
 5055   ctx_process (ctx, command);
 5056 }
 5057 
 5058 void ctx_dcmyk (Ctx *ctx, float c, float m, float y, float k)
 5059 {
 5060   CtxEntry command[3]=
 5061   {
 5062     ctx_f (CTX_COLOR, CTX_DCMYKA, c),
 5063     ctx_f (CTX_CONT, m, y),
 5064     ctx_f (CTX_CONT, k, 1.0f)
 5065   };
 5066   ctx_process (ctx, command);
 5067 }
 5068 
 5069 void ctx_dcmyka (Ctx *ctx, float c, float m, float y, float k, float a)
 5070 {
 5071   CtxEntry command[3]=
 5072   {
 5073     ctx_f (CTX_COLOR, CTX_DCMYKA, c),
 5074     ctx_f (CTX_CONT, m, y),
 5075     ctx_f (CTX_CONT, k, a)
 5076   };
 5077   ctx_process (ctx, command);
 5078 }
 5079 
 5080 #endif
 5081 
 5082 void
 5083 ctx_linear_gradient (Ctx *ctx, float x0, float y0, float x1, float y1)
 5084 {
 5085   CtxEntry command[2]=
 5086   {
 5087     ctx_f (CTX_LINEAR_GRADIENT, x0, y0),
 5088     ctx_f (CTX_CONT,            x1, y1)
 5089   };
 5090   ctx_process (ctx, command);
 5091 }
 5092 
 5093 void
 5094 ctx_radial_gradient (Ctx *ctx, float x0, float y0, float r0, float x1, 
 5095                      float y1, float r1)
 5096 {
 5097   CtxEntry command[3]=
 5098   {
 5099     ctx_f (CTX_RADIAL_GRADIENT, x0, y0),
 5100     ctx_f (CTX_CONT,            r0, x1),
 5101     ctx_f (CTX_CONT,            y1, r1)
 5102   };
 5103   ctx_process (ctx, command);
 5104 }
 5105 
 5106 void ctx_gradient_add_stop_u8
 5107 (Ctx *ctx, float pos, uint8_t r, uint8_t g, uint8_t b, uint8_t a)
 5108 {
 5109   CtxEntry entry = ctx_f (CTX_GRADIENT_STOP, pos, 0);
 5110   entry.data.u8[4+0] = r;
 5111   entry.data.u8[4+1] = g;
 5112   entry.data.u8[4+2] = b;
 5113   entry.data.u8[4+3] = a;
 5114   ctx_process (ctx, &entry);
 5115 }
 5116 
 5117 void ctx_gradient_add_stop
 5118 (Ctx *ctx, float pos, float r, float g, float b, float a)
 5119 {
 5120   int ir = r * 255;
 5121   int ig = g * 255;
 5122   int ib = b * 255;
 5123   int ia = a * 255;
 5124   ir = CTX_CLAMP (ir, 0,255);
 5125   ig = CTX_CLAMP (ig, 0,255);
 5126   ib = CTX_CLAMP (ib, 0,255);
 5127   ia = CTX_CLAMP (ia, 0,255);
 5128   ctx_gradient_add_stop_u8 (ctx, pos, ir, ig, ib, ia);
 5129 }
 5130 
 5131 void ctx_preserve (Ctx *ctx)
 5132 {
 5133   CTX_PROCESS_VOID (CTX_PRESERVE);
 5134 }
 5135 void ctx_fill (Ctx *ctx)
 5136 {
 5137   CTX_PROCESS_VOID (CTX_FILL);
 5138 }
 5139 void ctx_stroke (Ctx *ctx)
 5140 {
 5141   CTX_PROCESS_VOID (CTX_STROKE);
 5142 }
 5143 
 5144 static void ctx_state_init (CtxState *state);
 5145 
 5146 static void ctx_empty (Ctx *ctx)
 5147 {
 5148 #if CTX_RASTERIZER
 5149   if (ctx->renderer == NULL)
 5150 #endif
 5151     {
 5152       ctx->renderstream.count = 0;
 5153       ctx->renderstream.bitpack_pos = 0;
 5154     }
 5155 }
 5156 
 5157 void _ctx_set_store_clear (Ctx *ctx)
 5158 {
 5159   ctx->transformation |= CTX_TRANSFORMATION_STORE_CLEAR;
 5160 }
 5161 
 5162 #if CTX_EVENTS
 5163 static void
 5164 ctx_event_free (CtxEvent *event)
 5165 {
 5166   free (event);
 5167 }
 5168 
 5169 static void
 5170 ctx_collect_events (CtxEvent *event, void *data, void *data2)
 5171 {
 5172   Ctx *ctx = data;
 5173   CtxEvent *copy;
 5174   if (event->type == CTX_KEY_DOWN && !strcmp (event->string, "idle"))
 5175     return;
 5176   copy = malloc (sizeof (CtxEvent));
 5177   *copy = *event;
 5178   ctx_list_append_full (&ctx->events.events, copy, (void*)ctx_event_free, 
 5179                         NULL);
 5180 }
 5181 #endif
 5182 
 5183 static void _ctx_bindings_key_down (CtxEvent *event, void *data1, void 
 5184                                     *data2);
 5185 
 5186 void ctx_reset (Ctx *ctx)
 5187 {
 5188   //CTX_PROCESS_VOID (CTX_RESET);
 5189   //if (ctx->transformation & CTX_TRANSFORMATION_STORE_CLEAR)
 5190   //  { return; }
 5191   ctx_empty (ctx);
 5192   ctx_state_init (&ctx->state);
 5193 #if CTX_EVENTS
 5194   ctx_list_free (&ctx->events.items);
 5195 
 5196   if (ctx->events.ctx_get_event_enabled)
 5197   {
 5198     ctx_clear_bindings (ctx);
 5199     ctx_listen_full (ctx, 0, 0, ctx->events.width, ctx->events.height+1,
 5200                      CTX_PRESS|CTX_RELEASE|CTX_MOTION, ctx_collect_events, 
 5201                      ctx, ctx,
 5202                      NULL, NULL);
 5203     ctx_listen_full (ctx, 0,0,0,0,
 5204                      CTX_KEY_DOWN, _ctx_bindings_key_down, ctx, ctx,
 5205                      NULL, NULL);
 5206     ctx_listen_full (ctx, 0, 0, 0,0,
 5207                      CTX_KEY_DOWN, ctx_collect_events, ctx, ctx,
 5208                      NULL, NULL);
 5209     ctx_listen_full (ctx, 0, 0, 0,0,
 5210                      CTX_KEY_UP, ctx_collect_events, ctx, ctx,
 5211                      NULL, NULL);
 5212   }
 5213 #endif
 5214 }
 5215 
 5216 void ctx_begin_path (Ctx *ctx)
 5217 {
 5218   CTX_PROCESS_VOID (CTX_BEGIN_PATH);
 5219 }
 5220 
 5221 void ctx_clip (Ctx *ctx)
 5222 {
 5223   CTX_PROCESS_VOID (CTX_CLIP);
 5224 }
 5225 
 5226 void
 5227 ctx_set (Ctx *ctx, uint32_t key_hash, const char *string, int len);
 5228 
 5229 void ctx_start_move (Ctx *ctx)
 5230 {
 5231   ctx_set (ctx, CTX_start_move, "", 0);
 5232 }
 5233 
 5234 void ctx_save (Ctx *ctx)
 5235 {
 5236   CTX_PROCESS_VOID (CTX_SAVE);
 5237 }
 5238 void ctx_restore (Ctx *ctx)
 5239 {
 5240   CTX_PROCESS_VOID (CTX_RESTORE);
 5241 }
 5242 
 5243 void ctx_start_group (Ctx *ctx)
 5244 {
 5245   CTX_PROCESS_VOID (CTX_START_GROUP);
 5246 }
 5247 void ctx_end_group (Ctx *ctx)
 5248 {
 5249   CTX_PROCESS_VOID (CTX_END_GROUP);
 5250 }
 5251 
 5252 void ctx_line_width (Ctx *ctx, float x)
 5253 {
 5254   if (ctx->state.gstate.line_width != x)
 5255     CTX_PROCESS_F1 (CTX_LINE_WIDTH, x);
 5256 }
 5257 
 5258 void ctx_shadow_blur (Ctx *ctx, float x)
 5259 {
 5260 #if CTX_ENABLE_SHADOW_BLUR
 5261   if (ctx->state.gstate.shadow_blur != x)
 5262 #endif
 5263     CTX_PROCESS_F1 (CTX_SHADOW_BLUR, x);
 5264 }
 5265 
 5266 void ctx_shadow_rgba (Ctx *ctx, float r, float g, float b, float a)
 5267 {
 5268   CtxEntry command[3]=
 5269   {
 5270     ctx_f (CTX_SHADOW_COLOR, CTX_RGBA, r),
 5271     ctx_f (CTX_CONT, g, b),
 5272     ctx_f (CTX_CONT, a, 0)
 5273   };
 5274   ctx_process (ctx, command);
 5275 }
 5276 
 5277 void ctx_shadow_offset_x (Ctx *ctx, float x)
 5278 {
 5279 #if CTX_ENABLE_SHADOW_BLUR
 5280   if (ctx->state.gstate.shadow_offset_x != x)
 5281 #endif
 5282     CTX_PROCESS_F1 (CTX_SHADOW_OFFSET_X, x);
 5283 }
 5284 
 5285 void ctx_shadow_offset_y (Ctx *ctx, float x)
 5286 {
 5287 #if CTX_ENABLE_SHADOW_BLUR
 5288   if (ctx->state.gstate.shadow_offset_y != x)
 5289 #endif
 5290     CTX_PROCESS_F1 (CTX_SHADOW_OFFSET_Y, x);
 5291 }
 5292 
 5293 void
 5294 ctx_global_alpha (Ctx *ctx, float global_alpha)
 5295 {
 5296   if (ctx->state.gstate.global_alpha_f != global_alpha)
 5297     CTX_PROCESS_F1 (CTX_GLOBAL_ALPHA, global_alpha);
 5298 }
 5299 
 5300 float
 5301 ctx_get_global_alpha (Ctx *ctx)
 5302 {
 5303   return ctx->state.gstate.global_alpha_f;
 5304 }
 5305 
 5306 void
 5307 ctx_font_size (Ctx *ctx, float x)
 5308 {
 5309   CTX_PROCESS_F1 (CTX_FONT_SIZE, x);
 5310 }
 5311 
 5312 void
 5313 ctx_miter_limit (Ctx *ctx, float limit)
 5314 {
 5315   CTX_PROCESS_F1 (CTX_MITER_LIMIT, limit);
 5316 }
 5317 
 5318 float ctx_get_font_size  (Ctx *ctx)
 5319 {
 5320   return ctx->state.gstate.font_size;
 5321 }
 5322 
 5323 float ctx_get_line_width (Ctx *ctx)
 5324 {
 5325   return ctx->state.gstate.line_width;
 5326 }
 5327 
 5328 inline static int ctx_strcmp (const char *a, const char *b)
 5329 {
 5330   int i;
 5331   for (i = 0; a[i] && b[i]; a++, b++)
 5332     if (a[0] != b[0])
 5333       { return 1; }
 5334   if (a[0] == 0 && b[0] == 0) { return 0; }
 5335   return 1;
 5336 }
 5337 
 5338 inline static int ctx_strncmp (const char *a, const char *b, size_t n)
 5339 {
 5340   size_t i;
 5341   for (i = 0; a[i] && b[i] && i < n; a++, b++)
 5342     if (a[0] != b[0])
 5343       { return 1; }
 5344   return 0;
 5345 }
 5346 
 5347 static int ctx_strlen (const char *s)
 5348 {
 5349   int len = 0;
 5350   for (; *s; s++) { len++; }
 5351   return len;
 5352 }
 5353 
 5354 static char *ctx_strstr (const char *h, const char *n)
 5355 {
 5356   int needle_len = ctx_strlen (n);
 5357   if (n[0]==0)
 5358     { return (char *) h; }
 5359   while (h)
 5360     {
 5361       h = ctx_strchr (h, n[0]);
 5362       if (!h)
 5363         { return NULL; }
 5364       if (!ctx_strncmp (h, n, needle_len) )
 5365         { return (char *) h; }
 5366       h++;
 5367     }
 5368   return NULL;
 5369 }
 5370 
 5371 static int _ctx_resolve_font (const char *name)
 5372 {
 5373   for (int i = 0; i < ctx_font_count; i ++)
 5374     {
 5375       if (!ctx_strcmp (ctx_fonts[i].name, name) )
 5376         { return i; }
 5377     }
 5378   for (int i = 0; i < ctx_font_count; i ++)
 5379     {
 5380       if (ctx_strstr (ctx_fonts[i].name, name) )
 5381         { return i; }
 5382     }
 5383   return -1;
 5384 }
 5385 
 5386 static int ctx_resolve_font (const char *name)
 5387 {
 5388   int ret = _ctx_resolve_font (name);
 5389   if (ret >= 0)
 5390     { return ret; }
 5391   if (!ctx_strcmp (name, "regular") )
 5392     {
 5393       int ret = _ctx_resolve_font ("sans");
 5394       if (ret >= 0) { return ret; }
 5395       ret = _ctx_resolve_font ("serif");
 5396       if (ret >= 0) { return ret; }
 5397     }
 5398   return 0;
 5399 }
 5400 
 5401 void
 5402 _ctx_font (Ctx *ctx, const char *name)
 5403 {
 5404   ctx->state.gstate.font = ctx_resolve_font (name);
 5405 }
 5406 
 5407 void
 5408 ctx_set (Ctx *ctx, uint32_t key_hash, const char *string, int len)
 5409 {
 5410   if (len <= 0) len = strlen (string);
 5411   ctx_process_cmd_str (ctx, CTX_SET, string, key_hash, len);
 5412 }
 5413 
 5414 #include <unistd.h>
 5415 
 5416 const char *
 5417 ctx_get (Ctx *ctx, const char *key)
 5418 {
 5419   static char retbuf[32];
 5420   int len = 0;
 5421   CTX_PROCESS_U32(CTX_GET, ctx_strhash (key, 0), 0);
 5422   while (read (STDIN_FILENO, &retbuf[len], 1) != -1)
 5423     {
 5424       if(retbuf[len]=='\n')
 5425         break;
 5426       retbuf[++len]=0;
 5427     }
 5428   return retbuf;
 5429 }
 5430 
 5431 void
 5432 ctx_font (Ctx *ctx, const char *name)
 5433 {
 5434 #if CTX_BACKEND_TEXT
 5435   ctx_process_cmd_str (ctx, CTX_FONT, name, 0, 0);
 5436 #else
 5437   _ctx_font (ctx, name);
 5438 #endif
 5439 }
 5440 
 5441 void
 5442 ctx_identity (Ctx *ctx)
 5443 {
 5444   CTX_PROCESS_VOID (CTX_IDENTITY);
 5445 }
 5446 
 5447 void
 5448 ctx_apply_transform (Ctx *ctx, float a, float b,  // hscale, hskew
 5449                      float c, float d,  // vskew,  vscale
 5450                      float e, float f)  // htran,  vtran
 5451 {
 5452   CtxEntry command[3]=
 5453   {
 5454     ctx_f (CTX_APPLY_TRANSFORM, a, b),
 5455     ctx_f (CTX_CONT,            c, d),
 5456     ctx_f (CTX_CONT,            e, f)
 5457   };
 5458   ctx_process (ctx, command);
 5459 }
 5460 
 5461 void
 5462 ctx_get_transform  (Ctx *ctx, float *a, float *b,
 5463                     float *c, float *d,
 5464                     float *e, float *f)
 5465 {
 5466   if (a) { *a = ctx->state.gstate.transform.m[0][0]; }
 5467   if (b) { *b = ctx->state.gstate.transform.m[0][1]; }
 5468   if (c) { *c = ctx->state.gstate.transform.m[1][0]; }
 5469   if (d) { *d = ctx->state.gstate.transform.m[1][1]; }
 5470   if (e) { *e = ctx->state.gstate.transform.m[2][0]; }
 5471   if (f) { *f = ctx->state.gstate.transform.m[2][1]; }
 5472 }
 5473 
 5474 void ctx_apply_matrix (Ctx *ctx, CtxMatrix *matrix)
 5475 {
 5476   ctx_apply_transform (ctx,
 5477                        matrix->m[0][0], matrix->m[0][1],
 5478                        matrix->m[1][0], matrix->m[1][1],
 5479                        matrix->m[2][0], matrix->m[2][1]);
 5480 }
 5481 
 5482 void ctx_get_matrix (Ctx *ctx, CtxMatrix *matrix)
 5483 {
 5484   *matrix = ctx->state.gstate.transform;
 5485 }
 5486 
 5487 void ctx_set_matrix (Ctx *ctx, CtxMatrix *matrix)
 5488 {
 5489   ctx_identity (ctx);
 5490   ctx_apply_matrix (ctx, matrix);
 5491 }
 5492 
 5493 void ctx_rotate (Ctx *ctx, float x)
 5494 {
 5495   if (x == 0.0f)
 5496     return;
 5497   CTX_PROCESS_F1 (CTX_ROTATE, x);
 5498   if (ctx->transformation & CTX_TRANSFORMATION_SCREEN_SPACE)
 5499     { ctx->renderstream.count--; }
 5500 }
 5501 
 5502 void ctx_scale (Ctx *ctx, float x, float y)
 5503 {
 5504   if (x == 1.0f && y == 1.0f)
 5505     return;
 5506   CTX_PROCESS_F (CTX_SCALE, x, y);
 5507   if (ctx->transformation & CTX_TRANSFORMATION_SCREEN_SPACE)
 5508     { ctx->renderstream.count--; }
 5509 }
 5510 
 5511 void ctx_translate (Ctx *ctx, float x, float y)
 5512 {
 5513   if (x == 0.0f && y == 0.0f)
 5514     return;
 5515   CTX_PROCESS_F (CTX_TRANSLATE, x, y);
 5516   if (ctx->transformation & CTX_TRANSFORMATION_SCREEN_SPACE)
 5517     { ctx->renderstream.count--; }
 5518 }
 5519 
 5520 void ctx_line_to (Ctx *ctx, float x, float y)
 5521 {
 5522   if (!ctx->state.has_moved)
 5523     { CTX_PROCESS_F (CTX_MOVE_TO, x, y); }
 5524   else
 5525     { CTX_PROCESS_F (CTX_LINE_TO, x, y); }
 5526 }
 5527 
 5528 void ctx_move_to (Ctx *ctx, float x, float y)
 5529 {
 5530   CTX_PROCESS_F (CTX_MOVE_TO,x,y);
 5531 }
 5532 
 5533 void ctx_curve_to (Ctx *ctx, float x0, float y0,
 5534                    float x1, float y1,
 5535                    float x2, float y2)
 5536 {
 5537   CtxEntry command[3]=
 5538   {
 5539     ctx_f (CTX_CURVE_TO, x0, y0),
 5540     ctx_f (CTX_CONT,     x1, y1),
 5541     ctx_f (CTX_CONT,     x2, y2)
 5542   };
 5543   ctx_process (ctx, command);
 5544 }
 5545 
 5546 void ctx_round_rectangle (Ctx *ctx,
 5547                           float x0, float y0,
 5548                           float w, float h,
 5549                           float radius)
 5550 {
 5551   CtxEntry command[3]=
 5552   {
 5553     ctx_f (CTX_ROUND_RECTANGLE, x0, y0),
 5554     ctx_f (CTX_CONT,      w, h),
 5555     ctx_f (CTX_CONT,      radius, 0)
 5556   };
 5557   ctx_process (ctx, command);
 5558 }
 5559 
 5560 void ctx_view_box (Ctx *ctx,
 5561                    float x0, float y0,
 5562                    float w, float h)
 5563 {
 5564   CtxEntry command[3]=
 5565   {
 5566     ctx_f (CTX_VIEW_BOX, x0, y0),
 5567     ctx_f (CTX_CONT,     w, h)
 5568   };
 5569   ctx_process (ctx, command);
 5570 }
 5571 
 5572 void ctx_rectangle (Ctx *ctx,
 5573                     float x0, float y0,
 5574                     float w, float h)
 5575 {
 5576   CtxEntry command[3]=
 5577   {
 5578     ctx_f (CTX_RECTANGLE, x0, y0),
 5579     ctx_f (CTX_CONT,      w, h)
 5580   };
 5581   ctx_process (ctx, command);
 5582 }
 5583 
 5584 void ctx_rel_line_to (Ctx *ctx, float x, float y)
 5585 {
 5586   if (!ctx->state.has_moved)
 5587     { return; }
 5588   CTX_PROCESS_F (CTX_REL_LINE_TO,x,y);
 5589 }
 5590 
 5591 void ctx_rel_move_to (Ctx *ctx, float x, float y)
 5592 {
 5593   if (!ctx->state.has_moved)
 5594     {
 5595       CTX_PROCESS_F (CTX_MOVE_TO,x,y);
 5596       return;
 5597     }
 5598   CTX_PROCESS_F (CTX_REL_MOVE_TO,x,y);
 5599 }
 5600 
 5601 void ctx_line_cap (Ctx *ctx, CtxLineCap cap)
 5602 {
 5603   if (ctx->state.gstate.line_cap != cap)
 5604     CTX_PROCESS_U8 (CTX_LINE_CAP, cap);
 5605 }
 5606 void ctx_fill_rule (Ctx *ctx, CtxFillRule fill_rule)
 5607 {
 5608   if (ctx->state.gstate.fill_rule != fill_rule)
 5609     CTX_PROCESS_U8 (CTX_FILL_RULE, fill_rule);
 5610 }
 5611 void ctx_line_join (Ctx *ctx, CtxLineJoin join)
 5612 {
 5613   if (ctx->state.gstate.line_join != join)
 5614     CTX_PROCESS_U8 (CTX_LINE_JOIN, join);
 5615 }
 5616 void ctx_blend_mode (Ctx *ctx, CtxBlend mode)
 5617 {
 5618   CTX_PROCESS_U8 (CTX_BLEND_MODE, mode);
 5619 }
 5620 void ctx_compositing_mode (Ctx *ctx, CtxCompositingMode mode)
 5621 {
 5622   CTX_PROCESS_U8 (CTX_COMPOSITING_MODE, mode);
 5623 }
 5624 void ctx_text_align (Ctx *ctx, CtxTextAlign text_align)
 5625 {
 5626   CTX_PROCESS_U8 (CTX_TEXT_ALIGN, text_align);
 5627 }
 5628 void ctx_text_baseline (Ctx *ctx, CtxTextBaseline text_baseline)
 5629 {
 5630   CTX_PROCESS_U8 (CTX_TEXT_BASELINE, text_baseline);
 5631 }
 5632 void ctx_set_text_direction (Ctx *ctx, CtxTextDirection text_direction)
 5633 {
 5634   CTX_PROCESS_U8 (CTX_TEXT_DIRECTION, text_direction);
 5635 }
 5636 
 5637 void
 5638 ctx_rel_curve_to (Ctx *ctx,
 5639                   float x0, float y0,
 5640                   float x1, float y1,
 5641                   float x2, float y2)
 5642 {
 5643   if (!ctx->state.has_moved)
 5644     { return; }
 5645   CtxEntry command[3]=
 5646   {
 5647     ctx_f (CTX_REL_CURVE_TO, x0, y0),
 5648     ctx_f (CTX_CONT, x1, y1),
 5649     ctx_f (CTX_CONT, x2, y2)
 5650   };
 5651   ctx_process (ctx, command);
 5652 }
 5653 
 5654 void
 5655 ctx_rel_quad_to (Ctx *ctx,
 5656                  float cx, float cy,
 5657                  float x,  float y)
 5658 {
 5659   if (!ctx->state.has_moved)
 5660     { return; }
 5661   CtxEntry command[2]=
 5662   {
 5663     ctx_f (CTX_REL_QUAD_TO, cx, cy),
 5664     ctx_f (CTX_CONT, x, y)
 5665   };
 5666   ctx_process (ctx, command);
 5667 }
 5668 
 5669 void
 5670 ctx_quad_to (Ctx *ctx,
 5671              float cx, float cy,
 5672              float x,  float y)
 5673 {
 5674   if (!ctx->state.has_moved)
 5675     { return; }
 5676   CtxEntry command[2]=
 5677   {
 5678     ctx_f (CTX_QUAD_TO, cx, cy),
 5679     ctx_f (CTX_CONT, x, y)
 5680   };
 5681   ctx_process (ctx, command);
 5682 }
 5683 
 5684 void ctx_arc (Ctx  *ctx,
 5685               float x0, float y0,
 5686               float radius,
 5687               float angle1, float angle2,
 5688               int   direction)
 5689 {
 5690   CtxEntry command[3]=
 5691   {
 5692     ctx_f (CTX_ARC, x0, y0),
 5693     ctx_f (CTX_CONT, radius, angle1),
 5694     ctx_f (CTX_CONT, angle2, direction)
 5695   };
 5696   ctx_process (ctx, command);
 5697 }
 5698 
 5699 static int ctx_coords_equal (float x1, float y1, float x2, float y2, float 
 5700                              tol)
 5701 {
 5702   float dx = x2 - x1;
 5703   float dy = y2 - y1;
 5704   return dx*dx + dy*dy < tol*tol;
 5705 }
 5706 
 5707 static float
 5708 ctx_point_seg_dist_sq (float x, float y,
 5709                        float vx, float vy, float wx, float wy)
 5710 {
 5711   float l2 = ctx_pow2 (vx-wx) + ctx_pow2 (vy-wy);
 5712   if (l2 < 0.0001)
 5713     { return ctx_pow2 (x-vx) + ctx_pow2 (y-vy); }
 5714   float t = ( (x - vx) * (wx - vx) + (y - vy) * (wy - vy) ) / l2;
 5715   t = ctx_maxf (0, ctx_minf (1, t) );
 5716   float ix = vx + t * (wx - vx);
 5717   float iy = vy + t * (wy - vy);
 5718   return ctx_pow2 (x-ix) + ctx_pow2 (y-iy);
 5719 }
 5720 
 5721 static void
 5722 ctx_normalize (float *x, float *y)
 5723 {
 5724   float length = ctx_hypotf ( (*x), (*y) );
 5725   if (length > 1e-6f)
 5726     {
 5727       float r = 1.0f / length;
 5728       *x *= r;
 5729       *y *= r;
 5730     }
 5731 }
 5732 
 5733 void
 5734 ctx_arc_to (Ctx *ctx, float x1, float y1, float x2, float y2, float radius)
 5735 {
 5736   // XXX : should partially move into rasterizer to preserve comand
 5737   //       even if an arc preserves all geometry, just to ensure 
 5738   roundtripping
 5739   //       of data
 5740   /* from nanovg - but not quite working ; uncertain if arc or wrong
 5741    * transfusion is the cause.
 5742    */
 5743   float x0 = ctx->state.x;
 5744   float y0 = ctx->state.y;
 5745   float dx0,dy0, dx1,dy1, a, d, cx,cy, a0,a1;
 5746   int dir;
 5747   if (!ctx->state.has_moved)
 5748     { return; }
 5749   if (1)
 5750     {
 5751       // Handle degenerate cases.
 5752       if (ctx_coords_equal (x0,y0, x1,y1, 0.5f) ||
 5753           ctx_coords_equal (x1,y1, x2,y2, 0.5f) ||
 5754           ctx_point_seg_dist_sq (x1,y1, x0,y0, x2,y2) < 0.5 ||
 5755           radius < 0.5)
 5756         {
 5757           ctx_line_to (ctx, x1,y1);
 5758           return;
 5759         }
 5760     }
 5761   // Calculate tangential circle to lines (x0,y0)-(x1,y1) and (x1,y1)-(x2,
 5762                                            y2).
 5763   dx0 = x0-x1;
 5764   dy0 = y0-y1;
 5765   dx1 = x2-x1;
 5766   dy1 = y2-y1;
 5767   ctx_normalize (&dx0,&dy0);
 5768   ctx_normalize (&dx1,&dy1);
 5769   a = ctx_acosf (dx0*dx1 + dy0*dy1);
 5770   d = radius / ctx_tanf (a/2.0f);
 5771 #if 0
 5772   if (d > 10000.0f)
 5773     {
 5774       ctx_line_to (ctx, x1, y1);
 5775       return;
 5776     }
 5777 #endif
 5778   if ( (dx1*dy0 - dx0*dy1) > 0.0f)
 5779     {
 5780       cx = x1 + dx0*d + dy0*radius;
 5781       cy = y1 + dy0*d + -dx0*radius;
 5782       a0 = ctx_atan2f (dx0, -dy0);
 5783       a1 = ctx_atan2f (-dx1, dy1);
 5784       dir = 0;
 5785     }
 5786   else
 5787     {
 5788       cx = x1 + dx0*d + -dy0*radius;
 5789       cy = y1 + dy0*d + dx0*radius;
 5790       a0 = ctx_atan2f (-dx0, dy0);
 5791       a1 = ctx_atan2f (dx1, -dy1);
 5792       dir = 1;
 5793     }
 5794   ctx_arc (ctx, cx, cy, radius, a0, a1, dir);
 5795 }
 5796 
 5797 void
 5798 ctx_rel_arc_to (Ctx *ctx, float x1, float y1, float x2, float y2, float 
 5799                 radius)
 5800 {
 5801   x1 += ctx->state.x;
 5802   y1 += ctx->state.y;
 5803   x2 += ctx->state.x;
 5804   y2 += ctx->state.y;
 5805   ctx_arc_to (ctx, x1, y1, x2, y2, radius);
 5806 }
 5807 
 5808 void
 5809 ctx_exit (Ctx *ctx)
 5810 {
 5811   CTX_PROCESS_VOID (CTX_EXIT);
 5812 }
 5813 
 5814 #include <stdio.h>
 5815 #include <unistd.h>
 5816 
 5817 void
 5818 ctx_flush (Ctx *ctx)
 5819 {
 5820   /* XXX: should be fully moved into the renderers
 5821    *      to permit different behavior and get rid
 5822    *      of the extranous flush() vfunc.
 5823    */
 5824   ctx->rev++;
 5825 //  CTX_PROCESS_VOID (CTX_FLUSH);
 5826 #if 0
 5827   //printf (" \e[?2222h");
 5828   ctx_renderstream_compact (&ctx->renderstream);
 5829   for (int i = 0; i < ctx->renderstream.count - 1; i++)
 5830     {
 5831       CtxEntry *entry = &ctx->renderstream.entries[i];
 5832       fwrite (entry, 9, 1, stdout);
 5833 #if 0
 5834       uint8_t  *buf = (void *) entry;
 5835       for (int j = 0; j < 9; j++)
 5836         { printf ("%c", buf[j]); }
 5837 #endif
 5838     }
 5839   printf ("Xx.Xx.Xx.");
 5840   fflush (NULL);
 5841 #endif
 5842   if (ctx->renderer && ctx->renderer->flush)
 5843     ctx->renderer->flush (ctx->renderer);
 5844   ctx->renderstream.count = 0;
 5845   ctx_state_init (&ctx->state);
 5846 }
 5847 
 5848 ////////////////////////////////////////
 5849 
 5850 static void
 5851 ctx_matrix_invert (CtxMatrix *m)
 5852 {
 5853   CtxMatrix t = *m;
 5854   float invdet, det = m->m[0][0] * m->m[1][1] -
 5855                       m->m[1][0] * m->m[0][1];
 5856   if (det > -0.0000001f && det < 0.0000001f)
 5857     {
 5858       m->m[0][0] = m->m[0][1] =
 5859                      m->m[1][0] = m->m[1][1] =
 5860                                     m->m[2][0] = m->m[2][1] = 0.0;
 5861       return;
 5862     }
 5863   invdet = 1.0f / det;
 5864   m->m[0][0] = t.m[1][1] * invdet;
 5865   m->m[1][0] = -t.m[1][0] * invdet;
 5866   m->m[2][0] = (t.m[1][0] * t.m[2][1] - t.m[1][1] * t.m[2][0]) * invdet;
 5867   m->m[0][1] = -t.m[0][1] * invdet;
 5868   m->m[1][1] = t.m[0][0] * invdet;
 5869   m->m[2][1] = (t.m[0][1] * t.m[2][0] - t.m[0][0] * t.m[2][1]) * invdet ;
 5870 }
 5871 
 5872 static void
 5873 ctx_interpret_style (CtxState *state, CtxEntry *entry, void *data)
 5874 {
 5875   CtxCommand *c = (CtxCommand *) entry;
 5876   switch (entry->code)
 5877     {
 5878       case CTX_LINE_WIDTH:
 5879         state->gstate.line_width = ctx_arg_float (0);
 5880         break;
 5881 #if CTX_ENABLE_SHADOW_BLUR
 5882       case CTX_SHADOW_BLUR:
 5883         state->gstate.shadow_blur = ctx_arg_float (0);
 5884         break;
 5885       case CTX_SHADOW_OFFSET_X:
 5886         state->gstate.shadow_offset_x = ctx_arg_float (0);
 5887         break;
 5888       case CTX_SHADOW_OFFSET_Y:
 5889         state->gstate.shadow_offset_y = ctx_arg_float (0);
 5890         break;
 5891 #endif
 5892       case CTX_LINE_CAP:
 5893         state->gstate.line_cap = (CtxLineCap) ctx_arg_u8 (0);
 5894         break;
 5895       case CTX_FILL_RULE:
 5896         state->gstate.fill_rule = (CtxFillRule) ctx_arg_u8 (0);
 5897         break;
 5898       case CTX_LINE_JOIN:
 5899         state->gstate.line_join = (CtxLineJoin) ctx_arg_u8 (0);
 5900         break;
 5901       case CTX_COMPOSITING_MODE:
 5902         state->gstate.compositing_mode = (CtxCompositingMode) ctx_arg_u8 (0)
 5903                                          ;
 5904         break;
 5905       case CTX_BLEND_MODE:
 5906         state->gstate.blend_mode = (CtxBlend) ctx_arg_u8 (0);
 5907         break;
 5908       case CTX_TEXT_ALIGN:
 5909         ctx_state_set (state, CTX_text_align, ctx_arg_u8 (0) );
 5910         break;
 5911       case CTX_TEXT_BASELINE:
 5912         ctx_state_set (state, CTX_text_baseline, ctx_arg_u8 (0) );
 5913         break;
 5914       case CTX_TEXT_DIRECTION:
 5915         ctx_state_set (state, CTX_text_direction, ctx_arg_u8 (0) );
 5916         break;
 5917       case CTX_GLOBAL_ALPHA:
 5918         state->gstate.global_alpha_u8 = ctx_float_to_u8 (ctx_arg_float (0) )
 5919                                         ;
 5920         state->gstate.global_alpha_f = ctx_arg_float (0);
 5921         break;
 5922       case CTX_FONT_SIZE:
 5923         state->gstate.font_size = ctx_arg_float (0);
 5924         break;
 5925       case CTX_MITER_LIMIT:
 5926         state->gstate.miter_limit = ctx_arg_float (0);
 5927         break;
 5928 
 5929       case CTX_COLOR:
 5930         {
 5931           CtxColor *color = &state->gstate.source.color;
 5932           state->gstate.source.type = CTX_SOURCE_COLOR;
 5933           switch ( (int) ctx_arg_float (0) )
 5934             {
 5935               case CTX_RGB:
 5936                 ctx_color_set_rgba (state, color, c->rgba.r, c->rgba.g, c->
 5937                                     rgba.b, 1.0f);
 5938                 break;
 5939               case CTX_RGBA:
 5940                 ctx_color_set_rgba (state, color, c->rgba.r, c->rgba.g, c->
 5941                                     rgba.b, c->rgba.a);
 5942                 break;
 5943               case CTX_DRGBA:
 5944                 ctx_color_set_drgba (state, color, c->rgba.r, c->rgba.g, c->
 5945                                      rgba.b, c->rgba.a);
 5946                 break;
 5947 #if CTX_ENABLE_CMYK
 5948               case CTX_CMYKA:
 5949                 ctx_color_set_cmyka (state, color, c->cmyka.c, c->cmyka.m, 
 5950                                      c->cmyka.y, c->cmyka.k, c->cmyka.a);
 5951                 break;
 5952               case CTX_CMYK:
 5953                 ctx_color_set_cmyka (state, color, c->cmyka.c, c->cmyka.m, 
 5954                                      c->cmyka.y, c->cmyka.k, 1.0f);
 5955                 break;
 5956               case CTX_DCMYKA:
 5957                 ctx_color_set_dcmyka (state, color, c->cmyka.c, c->cmyka.m, 
 5958                                       c->cmyka.y, c->cmyka.k, c->cmyka.a);
 5959                 break;
 5960               case CTX_DCMYK:
 5961                 ctx_color_set_dcmyka (state, color, c->cmyka.c, c->cmyka.m, 
 5962                                       c->cmyka.y, c->cmyka.k, 1.0f);
 5963                 break;
 5964 #endif
 5965               case CTX_GRAYA:
 5966                 ctx_color_set_graya (state, color, c->graya.g, c->graya.a);
 5967                 break;
 5968               case CTX_GRAY:
 5969                 ctx_color_set_graya (state, color, c->graya.g, 1.0f);
 5970                 break;
 5971             }
 5972         }
 5973         break;
 5974       case CTX_SET_RGBA_U8:
 5975         //ctx_source_deinit (&state->gstate.source);
 5976         state->gstate.source.type = CTX_SOURCE_COLOR;
 5977         ctx_color_set_RGBA8 (state, &state->gstate.source.color,
 5978                              ctx_arg_u8 (0),
 5979                              ctx_arg_u8 (1),
 5980                              ctx_arg_u8 (2),
 5981                              ctx_arg_u8 (3) );
 5982         //for (int i = 0; i < 4; i ++)
 5983         //  state->gstate.source.color.rgba[i] = ctx_arg_u8(i);
 5984         break;
 5985 #if 0
 5986       case CTX_SET_RGBA_STROKE:
 5987         //ctx_source_deinit (&state->gstate.source);
 5988         state->gstate.source_stroke = state->gstate.source;
 5989         state->gstate.source_stroke.type = CTX_SOURCE_COLOR;
 5990         for (int i = 0; i < 4; i ++)
 5991           { state->gstate.source_stroke.color.rgba[i] = ctx_arg_u8 (i); }
 5992         break;
 5993 #endif
 5994       //case CTX_TEXTURE:
 5995       //  state->gstate.source.type = CTX_SOURCE_
 5996       //  break;
 5997       case CTX_LINEAR_GRADIENT:
 5998         {
 5999           float x0 = ctx_arg_float (0);
 6000           float y0 = ctx_arg_float (1);
 6001           float x1 = ctx_arg_float (2);
 6002           float y1 = ctx_arg_float (3);
 6003           float dx, dy, length, start, end;
 6004           ctx_user_to_device (state, &x0, &y0);
 6005           ctx_user_to_device (state, &x1, &y1);
 6006           length = ctx_hypotf (x1-x0,y1-y0);
 6007           dx = (x1-x0) / length;
 6008           dy = (y1-y0) / length;
 6009           start = (x0 * dx + y0 * dy) / length;
 6010           end =   (x1 * dx + y1 * dy) / length;
 6011           state->gstate.source.linear_gradient.length = length;
 6012           state->gstate.source.linear_gradient.dx = dx;
 6013           state->gstate.source.linear_gradient.dy = dy;
 6014           state->gstate.source.linear_gradient.start = start;
 6015           state->gstate.source.linear_gradient.end = end;
 6016           state->gstate.source.linear_gradient.rdelta = (end-start)!=0.0?1.
 6017                                                         0f/(end - start):0.
 6018                                                         0;
 6019           state->gstate.source.type = CTX_SOURCE_LINEAR_GRADIENT;
 6020           state->gstate.source.transform = state->gstate.transform;
 6021           ctx_matrix_invert (&state->gstate.source.transform);
 6022         }
 6023         break;
 6024       case CTX_RADIAL_GRADIENT:
 6025         {
 6026           float x0 = ctx_arg_float (0);
 6027           float y0 = ctx_arg_float (1);
 6028           float r0 = ctx_arg_float (2);
 6029           float x1 = ctx_arg_float (3);
 6030           float y1 = ctx_arg_float (4);
 6031           float r1 = ctx_arg_float (5);
 6032           state->gstate.source.radial_gradient.x0 = x0;
 6033           state->gstate.source.radial_gradient.y0 = y0;
 6034           state->gstate.source.radial_gradient.r0 = r0;
 6035           state->gstate.source.radial_gradient.x1 = x1;
 6036           state->gstate.source.radial_gradient.y1 = y1;
 6037           state->gstate.source.radial_gradient.r1 = r1;
 6038           state->gstate.source.radial_gradient.rdelta = (r1 - r0) != 0.0 ? 
 6039                                                         1.0f/(r1-r0):0.0;
 6040           state->gstate.source.type      = CTX_SOURCE_RADIAL_GRADIENT;
 6041           state->gstate.source.transform = state->gstate.transform;
 6042           ctx_matrix_invert (&state->gstate.source.transform);
 6043         }
 6044         break;
 6045     }
 6046 }
 6047 
 6048 static void
 6049 ctx_interpret_transforms (CtxState *state, CtxEntry *entry, void *data)
 6050 {
 6051   switch (entry->code)
 6052     {
 6053       case CTX_SAVE:
 6054         ctx_gstate_push (state);
 6055         break;
 6056       case CTX_RESTORE:
 6057         ctx_gstate_pop (state);
 6058         break;
 6059       case CTX_IDENTITY:
 6060         ctx_matrix_identity (&state->gstate.transform);
 6061         break;
 6062       case CTX_TRANSLATE:
 6063         ctx_matrix_translate (&state->gstate.transform,
 6064                               ctx_arg_float (0), ctx_arg_float (1) );
 6065         break;
 6066       case CTX_SCALE:
 6067         ctx_matrix_scale (&state->gstate.transform,
 6068                           ctx_arg_float (0), ctx_arg_float (1) );
 6069         break;
 6070       case CTX_ROTATE:
 6071         ctx_matrix_rotate (&state->gstate.transform, ctx_arg_float (0) );
 6072         break;
 6073       case CTX_APPLY_TRANSFORM:
 6074         {
 6075           CtxMatrix m;
 6076           ctx_matrix_set (&m,
 6077                           ctx_arg_float (0), ctx_arg_float (1),
 6078                           ctx_arg_float (2), ctx_arg_float (3),
 6079                           ctx_arg_float (4), ctx_arg_float (5) );
 6080           ctx_matrix_multiply (&state->gstate.transform,
 6081                                &state->gstate.transform, &m); // XXX verify 
 6082                                order
 6083         }
 6084 #if 0
 6085         ctx_matrix_set (&state->gstate.transform,
 6086                         ctx_arg_float (0), ctx_arg_float (1),
 6087                         ctx_arg_float (2), ctx_arg_float (3),
 6088                         ctx_arg_float (4), ctx_arg_float (5) );
 6089 #endif
 6090         break;
 6091     }
 6092 }
 6093 
 6094 static inline void
 6095 ctx_matrix_apply_transform (const CtxMatrix *m, float *x, float *y)
 6096 {
 6097   float x_in = *x;
 6098   float y_in = *y;
 6099   *x = ( (x_in * m->m[0][0]) + (y_in * m->m[1][0]) + m->m[2][0]);
 6100   *y = ( (y_in * m->m[1][1]) + (x_in * m->m[0][1]) + m->m[2][1]);
 6101 }
 6102 
 6103 void
 6104 ctx_user_to_device (CtxState *state, float *x, float *y)
 6105 {
 6106   ctx_matrix_apply_transform (&state->gstate.transform, x, y);
 6107 }
 6108 
 6109 void
 6110 ctx_user_to_device_distance (CtxState *state, float *x, float *y)
 6111 {
 6112   const CtxMatrix *m = &state->gstate.transform;
 6113   ctx_matrix_apply_transform (m, x, y);
 6114   *x -= m->m[2][0];
 6115   *y -= m->m[2][1];
 6116 }
 6117 
 6118 #if CTX_BITPACK_PACKER
 6119 
 6120 #if CTX_BITPACK
 6121 static float
 6122 find_max_dev (CtxEntry *entry, int nentrys)
 6123 {
 6124   float max_dev = 0.0;
 6125   for (int c = 0; c < nentrys; c++)
 6126     {
 6127       for (int d = 0; d < 2; d++)
 6128         {
 6129           if (entry[c].data.f[d] > max_dev)
 6130             { max_dev = entry[