Changeset 19 in projects


Ignore:
Timestamp:
Sep 22, 2008, 2:12:54 AM (11 years ago)
Author:
sven
Message:

The Gtk::PaperTape gtkmm implementation of the GtkPaperTape widget. Now
quite more object oriented, using a MVC approach. There's much still to
do.

I commit these files now because I won't be able to work at the project
in the next week(s). Afterwards I plan to make more use of the
versioning features, commiting on a more regular basis.

-- Sven @ workstation

Location:
visualisator
Files:
22 added
4 deleted
5 edited

Legend:

Unmodified
Added
Removed
  • visualisator

    • Property svn:ignore set to
      *.o
      gtk
      cli
  • visualisator/Makefile

    r9 r19  
     1CAIRO_CFLAGS=`pkg-config --cflags cairo`
     2GTKMM_CFLAGS=`pkg-config --cflags gtkmm-2.4`
     3CAIRO_LIBS=`pkg-config --libs cairo`
     4GTKMM_LIBS=`pkg-config --libs gtkmm-2.4`
     5CPP=g++
     6CFLAGS=-Wall
    17
    2 CFLAGS       = -Wall
    3 CAIRO_CFLAGS = `pkg-config --cflags cairo`
    4 GTK_CFLAGS   = `pkg-config --cflags gtk+-2.0`
    5 CAIRO_LFLAGS = `pkg-config --libs cairo`
    6 GTK_LFLAGS   = `pkg-config --libs gtk+-2.0`
    7 # GTK uses Cairo, therefore $(GTK_FLAGS) doesn't need $(CAIRO_FLAGS), too
    8 
    9 all: cli gtk
     8gtk: gtk.cc gtkpapertape.o gtkpapertapeview.o gtkpapertapefile.o gtkpapertapecolor.o gtkpapertapezoom.o lochstreifen.o gtkpapertapeexporter.o
     9        $(CPP) $(GTKMM_CFLAGS) $^ -o $@ $(GTKMM_LIBS)
    1010
    1111cli: cli.c lochstreifen.o
    12         gcc $(CFLAGS) $(CAIRO_LFLAGS) $(CAIRO_CFLAGS) -o cli lochstreifen.o cli.c
     12        $(CC) $(CAIRO_CFLAGS) $^ $(CAIRO_LIBS) -o $@
    1313
    14 # cli was formerly:
    15 #cmd: create-image.c $(BACKEND)
    16 #       gcc -o binary $(CAIROFLAGS) create-image.c $(BACKEND)
     14gtkpapertape.o: gtkpapertape.cc gtkpapertape.h
     15        $(CPP) $(CFLAGS) $(GTKMM_CFLAGS) -c gtkpapertape.cc
    1716
    18 gtk: gtk.c gtkpapertape.o
    19         gcc $(CFLAGS) $(GTK_LFLAGS) $(GTK_CFLAGS) -o gtk gtkpapertape.o lochstreifen.o gtk.c
     17gtkpapertapeview.o: gtkpapertapeview.cc gtkpapertapeview.h
     18        $(CPP) $(CFLAGS) $(GTKMM_CFLAGS) -c gtkpapertapeview.cc
    2019
     20gtkpapertapefile.o: gtkpapertapefile.cc gtkpapertapefile.h
     21        $(CPP) $(CFLAGS) $(GTKMM_CFLAGS) -c gtkpapertapefile.cc
     22       
     23gtkpapertapeexporter.o: gtkpapertapeexporter.cc gtkpapertapeexporter.h
     24        $(CPP) $(CFLAGS) $(GTKMM_CFLAGS) -c gtkpapertapeexporter.cc
    2125
    22 gtkpapertape.o: lochstreifen.o gtkpapertape.c gtkpapertape.h
    23         gcc $(CFLAGS) $(GTK_CFLAGS) -c gtkpapertape.c
     26gtkpapertapecolor.o: gtkpapertapecolor.cc gtkpapertapecolor.h
     27        $(CPP) $(CFLAGS) $(GTKMM_CFLAGS) -c gtkpapertapecolor.cc
     28
     29gtkpapertapezoom.o: gtkpapertapezoom.cc gtkpapertapezoom.h
     30        $(CPP) $(CFLAGS) $(GTKMM_CFLAGS) -c gtkpapertapezoom.cc
    2431
    2532lochstreifen.o: lochstreifen.c lochstreifen.h
    26         gcc $(CFLAGS) $(CAIRO_CFLAGS) -c lochstreifen.c
     33        $(CC) $(CFLAGS) $(CAIRO_CFLAGS) -c lochstreifen.c
    2734
    2835clean:
    29         rm *.o gtk cli
     36        rm -v *.o
  • visualisator/gtkpapertape.h

    r9 r19  
     1#ifndef __GTK_PAPER_TAPE_H__
     2#define __GTK_PAPER_TAPE_H__
     3
     4#include "gtkmm/box.h"
     5#include "gtk/gtk.h"
     6#include <gtkmm/uimanager.h>
     7#include <gtkmm/dialog.h>
     8
     9// predefine for usage in other header files
     10namespace Gtk
     11{ class PaperTape; }
     12#include "gtkpapertapeview.h"
     13#include "gtkpapertapefile.h"
     14
     15typedef unsigned char byte_t;
     16
     17namespace Gtk {
     18
    119/**
    2  *
    3  * The paper tape GTK widget
    4  *
    5  * This widget wraps the pure cairo widget "LOCHSTREIFEN" with some
    6  * GTK widgets (which implement scrolling, mouse events, menues for
    7  * changing parameters, etc.) and adds events and signals for simple
    8  * interaction and use in applications.
    9  *
    10  * It can produce high quality SVG and PNG files (apart from displaying
    11  * the paper tape on the screen) and is highly configurable. With
    12  * only a few lines of code you can use this widget in your own
    13  * programs, gtk.c shows an exemplar implementation in only about
    14  * 160 lines of C code.
    15  *
    16  * Started 05.06.2008 13:13 (the first new project in the SVN)
    17  * Copyright (C) 2008  Sven Köppel
    18  *
    19  * This program is free software; you can redistribute
    20  * it and/or modify it under the terms of the GNU General
    21  * Public License as published by the Free Software
    22  * Foundation; either version 3 of the License, or (at
    23  * your option) any later version.
    24  *
    25  * This program is distributed in the hope that it will
    26  * be useful, but WITHOUT ANY WARRANTY; without even the
    27  * implied warranty of MERCHANTABILITY or FITNESS FOR A
    28  * PARTICULAR PURPOSE. See the GNU General Public License
    29  * for more details.
    30  *
    31  * You should have received a copy of the GNU General
    32  * Public License along with this program; if not, see
    33  * <http://www.gnu.org/licenses/>.
     20 * Klasse könnte GtkWidget erweitern und dann selbst das Haupt
     21 * master drumherumwidget sein, was automatisch richtige Kinder
     22 * herzaubert, inkl. Scrolling und beispielsweise greaterzoom-ding.
     23 * Oder dann das IO teil, usw.
    3424 *
    3525 **/
     26class PaperTape : public VBox
     27{
     28       
     29public:
     30        PaperTapeView* view;
     31        PaperTapeFile* model;
     32        Window* parent_window;
     33       
     34private:
     35       
     36        static Glib::ustring ui_info;
     37        static GtkActionEntry ui_common_entries[];
     38        static GtkActionEntry ui_file_entries[];
     39        static GtkActionEntry ui_editor_entries[];
     40        static GtkToggleActionEntry ui_toggle_entries[];
     41        Glib::RefPtr<Gtk::UIManager> ui_manager;
     42        void make_menu();
     43        void menu_actions(const Glib::RefPtr<Action>& action);
    3644
    37 #ifndef GTK_PAPER_TAPE_H
    38 #define GTK_PAPER_TAPE_H
     45public:
     46        PaperTape(Window& parent_window);
     47       
     48        /**
     49         * Runs the dialog. This is just like dialog.run(),
     50         * but with the correct parent window (modal dialog),
     51         * which is saved in this widget.
     52         **/
     53        int run_dialog(Dialog& dialog) {
     54                dialog.set_transient_for(*this->parent_window);
     55                return dialog.run();
     56        }
    3957
    40 #include <glib.h>
    41 #include <glib-object.h>
    42 #include <gtk/gtk.h>
    43 #include "lochstreifen.h"
     58        /**
     59         * Open a blank file. This will ask if user wants to close
     60         * file and open, if yes, a new blank file.
     61         **/
     62        //void new_file();
     63        /**
     64         * Show a file dialog to open an existing file. This will
     65         * ask the user if he wants to close the current file.
     66         **/
     67        //void open_file();
     68        /**
     69         * Ask the user if he wants to close the current file. If so,
     70         * close it, leaving with no file opened (splash screen)
     71         **/
     72        //void close_file();
     73        /**
     74         * Check if a file is opened.
     75         * @returns true if a file is opened.
     76         **/
     77        //boolean file_is_open();
     78};
    4479
    4580
    46 G_BEGIN_DECLS
    47 
    48 /*#define GTK_PAPER_TAPE_TYPE              (gtk_paper_tape_get_type())
    49 #define GTK_TYPE_PAPER_TAPE              (gtk_paper_tape_get_type())
    50 #define GTK_PAPER_TAPE(obj)              (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_PAPER_TAPE, GtkPaperTape))
    51 #define GTK_PAPER_TAPE_CLASS(klasse)     (G_TYPE_CHECK_CLASS_CAST((klasse), GTK_TYPE_PAPER_TAPE, GtkPaperTapeClass))
    52 #define GTK_IS_PAPER_TAPE(obj)           (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_PAPER_TAPE))
    53 #define GTK_IS_PAPER_TAPE_CLASS(klasse)  (G_TYPE_CHECK_CLASS_TYPE((klasse), GTK_TYPE_PAPER_TAPE))
    54 #define GTK_PAPER_TAPE_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_PAPER_TAPE, GtkPaperTapeClass))*/
    55 
    56 #define GTK_PAPER_TAPE_TYPE            (gtk_paper_tape_get_type ())
    57 #define GTK_PAPER_TAPE(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTK_PAPER_TAPE_TYPE, GtkPaperTape))
    58 #define GTK_PAPER_TAPE_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_PAPER_TAPE_TYPE, GtkPaperTapeClass))
    59 #define GTK_IS_PAPER_TAPE(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GTK_PAPER_TAPE_TYPE))
    60 #define GTK_IS_PAPER_TAPE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_PAPER_TAPE_TYPE))
    61 
    62 typedef struct _GtkPaperTape GtkPaperTape;
    63 typedef struct _GtkPaperTapeClass GtkPaperTapeClass;
    64 
    65 struct _GtkPaperTape {
    66   //GObject parent;
    67   GtkWidget widget; // was GObject parent;
    68   // instance members
    69 
    70   /** Main window where this widget belongs to
    71    * (to be used e.g. for modal dialogs) */
    72   GtkWidget *parent_window;
    73 
    74   /** The famous LOCHSTREIFEN widget  */
    75   LOCHSTREIFEN *lochstreifen;
    76 
    77   /** The Statusbar where the mouse movement messages appear */
    78   GtkWidget *statusbar;
    79 
    80   /**
    81    * The GtkScrolledWindow where the
    82    * GtkDrawingArea resides
    83    */
    84   GtkWidget *scroll;
    85   GtkWidget *draw;
    86 
    87   /*< private >*/
    88   GtkWidget *menu_toggle_fit_screen;
    89   GTimer *last_statusbar_update;
    90 };
    91 
    92 struct _GtkPaperTapeClass {
    93   GtkWidgetClass parent_class; //GObjectClass parent;
    94 };
    95 
    96 GType gtk_paper_tape_get_type(void);
    97 
    98 GtkWidget*     gtk_paper_tape_new();
    99 
    100 void gtk_paper_tape_menu_export(GtkPaperTape *papertape, GtkWidget *target_menu);
    101 void gtk_paper_tape_menu_view(GtkPaperTape *papertape, GtkWidget *target_menu);
    102 void gtk_paper_tape_menu_colors(GtkPaperTape *papertape, GtkWidget *target_menu);
    103 
    104 /* fast "almost macro" functions */
    105 GtkWidget *fast_color_menuitem(const GtkWidget *parentmenu, const char *dialog_title, const char *labeltext, GdkColor *initialColor, GtkSizeGroup *label_nice_sizegroup);
    106 GtkWidget *fast_stock_menuitem(const GtkWidget *parentmenu, const gchar *stock_id);
    107 GtkWidget *fast_menuitem(const GtkWidget *parentmenu, const gchar *label);
    108 GtkWidget *fast_menu_tearoff(const GtkWidget *parentmenu);
    109 GtkWidget *fast_menu_seperator(const GtkWidget *parentmenu);
    110 GdkColor *color_cairo2gdk(cairo_pattern_t *pattern);
    111 
    112 void gtk_paper_tape_set_data(GtkPaperTape* papertape, int length, byte_t *data);
    113 void gtk_paper_tape_set_null_bytes(GtkPaperTape *papertape, int beginning, int end);
    114 
    115 gboolean gtk_paper_tape_read_from_file(GtkPaperTape* papertape, char *filename);
    116 GtkWidget *gtk_paper_tape_get_whole_box(GtkPaperTape *papertape);
    117 
    118 G_END_DECLS
    119 
    120 #endif /* GTK_PAPER_TAPE_H */
     81}; // namespace Gtk
     82#endif // __GTK_PAPER_TAPE_H__
  • visualisator/lochstreifen.c

    r18 r19  
    6666        l->zero_code_hole_color       = LOCHSTREIFEN_DEFAULT_ZERO_CODE_HOLE_COLOR;
    6767        l->feed_hole_color            = LOCHSTREIFEN_DEFAULT_FEED_HOLE_COLOR;
    68         l->matrix                     = malloc (sizeof(cairo_matrix_t));
    69         // default matrix: 1:1 original.
    70         l->matrix->xx = 1;   l->matrix->yx = 0;
    71         l->matrix->xy = 0;   l->matrix->yy = 1;
    72         l->matrix->x0 = 0;   l->matrix->y0 = 0;
     68        cairo_matrix_init(&l->matrix, 1, 0, 0, 1, 0, 0); // default = 1:1 original
     69        l->matrix_inverse             = l->matrix;
    7370
    7471        return l;
     72}
     73
     74/**
     75 * Copy everything from the LOCHSTREIFEN template, except the data. They
     76 * won't be copied, just set, because LOCHSTREIFEN doesn't manage your
     77 * data. If you want to copy them, call something like
     78 *   LOCHSTREIFEN* copy = lochstreifen_copy(old);
     79 *   byte_t* new_data = malloc(old->data_length);
     80 *   memcpy(new_data, old->data, old->data_length);
     81 *   lochstreifen_set_data(copy, old->data_length, new_data);
     82 **/
     83LOCHSTREIFEN* lochstreifen_copy(const LOCHSTREIFEN* template) {
     84        LOCHSTREIFEN *l = malloc (sizeof(LOCHSTREIFEN));
     85        #define COPY_RGBA_PATTERN(name) { double r,g,b,a; \
     86                if(!cairo_pattern_get_rgba(template->name, &r, &g, &b, &a)) \
     87                        l->name = cairo_pattern_create_rgba(r,g,b,a); }
     88       
     89        // make it quite verbose ;-)
     90        l->data_length                = template->data_length;
     91        l->data                       = template->data;
     92        l->highlight_region_start     = template->highlight_region_start;
     93        l->highlight_region_end       = template->highlight_region_end;
     94        COPY_RGBA_PATTERN(highlight_region_color);
     95        l->highlight_row_number       = template->highlight_row_number;
     96        COPY_RGBA_PATTERN(highlight_row_color);
     97        l->highlight_bit_row          = template->highlight_bit_row;
     98        l->highlight_bit_track        = template->highlight_bit_track;
     99        COPY_RGBA_PATTERN(highlight_bit_color);
     100        l->clip                       = malloc(sizeof(cairo_rectangle_t));
     101        memcpy(l->clip, template->clip, sizeof(cairo_rectangle_t));
     102        COPY_RGBA_PATTERN(outer_background_color);
     103        COPY_RGBA_PATTERN(papertape_background_color);
     104        COPY_RGBA_PATTERN(one_code_hole_color);
     105        COPY_RGBA_PATTERN(zero_code_hole_color);
     106        COPY_RGBA_PATTERN(feed_hole_color);
     107        l->matrix                     = template->matrix;
     108        l->matrix_inverse             = template->matrix_inverse;
     109
     110        return l;
     111}
     112
     113/**
     114 * Delete every mallocated structure in the LOCHSTREIFEN (colors, etc.),
     115 * *except* from the data. You have to manage them on your own.
     116 * In the end, it will free the LOCHSTREIFEN itself.
     117 * @return Nothing, because there's nothing left. Except your data, okay.
     118 **/
     119void lochstreifen_free(LOCHSTREIFEN* l) {
     120        if(l->highlight_region_color     != NULL)  free(l->highlight_region_color);
     121        if(l->highlight_row_color        != NULL)  free(l->highlight_row_color);
     122        if(l->highlight_bit_color        != NULL)  free(l->highlight_bit_color);
     123        if(l->clip                       != NULL)  free(l->clip);
     124        if(l->outer_background_color     != NULL)  free(l->outer_background_color);
     125        if(l->papertape_background_color != NULL)  free(l->papertape_background_color);
     126        if(l->one_code_hole_color        != NULL)  free(l->one_code_hole_color);
     127        if(l->zero_code_hole_color       != NULL)  free(l->zero_code_hole_color);
     128        if(l->feed_hole_color            != NULL)  free(l->feed_hole_color);
    75129}
    76130
     
    93147       
    94148        if(l != NULL)
    95                 fprintf(stderr, "Debugging papertape at %x:\n", l);
     149                fprintf(stderr, "Debugging papertape at %p:\n", l);
    96150        else {
    97151                fprintf(stderr, "Cannot debug: Papertape is NULL!\n");
     
    155209       
    156210        // 5. Point: Affine Matrix
    157         if(l->matrix == NULL)
    158                 fprintf(stderr, " * Matrix: disabled\n");
    159         else {
    160                 fprintf(stderr, " * Matrix: ENABLED\n");
    161                 fprintf(stderr, "   x_new = [xx=%f]*x + [xy=%f]*y + [x0=%f]\n",
    162                         l->matrix->xx, l->matrix->xy, l->matrix->x0);
    163                 fprintf(stderr, "   y_new = [yx=%f]*x + [yy=%f]*y + [y0=%f]\n",
    164                         l->matrix->yx, l->matrix->yy, l->matrix->y0);
    165                 fprintf(stderr, "   source dimensions: x_max = %f x y_max = %f\n",
    166                         LOCHSTREIFEN_LENGTH, LOCHSTREIFEN_WIDTH);
    167                 fprintf(stderr, "   target dimensions: width = %i x height = %i\n",
    168                         lochstreifen_get_target_width(l),
    169                         lochstreifen_get_target_height(l));
    170         }
     211        fprintf(stderr, " * Current transformation matrix:\n");
     212        fprintf(stderr, "   x_new = [xx=%f]*x + [xy=%f]*y + [x0=%f]\n",
     213                l->matrix.xx, l->matrix.xy, l->matrix.x0);
     214        fprintf(stderr, "   y_new = [yx=%f]*x + [yy=%f]*y + [y0=%f]\n",
     215                l->matrix.yx, l->matrix.yy, l->matrix.y0);
     216        fprintf(stderr, "   source dimensions: x_max = %f x y_max = %f\n",
     217                LOCHSTREIFEN_LENGTH, LOCHSTREIFEN_WIDTH);
     218        fprintf(stderr, "   target dimensions: width = %i x height = %i\n",
     219                lochstreifen_get_target_width(l),
     220                lochstreifen_get_target_height(l));
    171221       
    172222        // 6. Point: Debugging
     
    185235void lochstreifen_set_data(LOCHSTREIFEN *l, int data_length, byte_t *data) {
    186236        l->data_length = data_length;
    187         if(l->data != NULL)
    188                 free(l->data);
     237        //if(l->data != NULL)
     238        //      free(l->data);
    189239        l->data = data;
    190240}
     
    240290 *          highlight region
    241291 **/
    242 void lochstreifen_set_highlight_region(LOCHSTREIFEN *l, int start, int end) {
     292void lochstreifen_set_highlight_region(LOCHSTREIFEN *l, row_t start, row_t end) {
    243293        l->highlight_region_start = start;
    244294        l->highlight_region_end   = end;
     
    252302 * @return TRUE if there is an highlight selection, FALSE otherwiese
    253303 **/
    254 int lochstreifen_get_highlight_region(LOCHSTREIFEN *l, int *start, int *end) {
    255         if(l->highlight_region_color == NULL)
     304int lochstreifen_get_highlight_region(LOCHSTREIFEN *l, row_t *start, row_t *end) {
     305        if(l->highlight_region_color == NULL || l->highlight_region_start == LOCHSTREIFEN_NO_ROW)
    256306                return 0;
    257307        if(start != NULL)
     
    266316 **/
    267317void lochstreifen_remove_highlight_region(LOCHSTREIFEN *l) {
    268         l->highlight_region_color = NULL;
     318        //l->highlight_region_color = NULL;
     319        // was stupid, this is more intelligent:
     320        l->highlight_region_start = LOCHSTREIFEN_NO_ROW;
    269321}
    270322
     
    285337 * GtkPaperTape.
    286338 **/
    287 void lochstreifen_set_highlight_row(LOCHSTREIFEN *l, int number_of_row) {
     339void lochstreifen_set_highlight_row(LOCHSTREIFEN *l, row_t number_of_row) {
    288340        l->highlight_row_number = number_of_row;
    289341        if(l->highlight_row_color == NULL)
     
    292344
    293345/**
    294  * Get the highlighted special row. If there is no highlighted row, it will return a value
    295  * less than zero (e.g. -1).
     346 * Get the highlighted special row. If there is no highlighted row, it will return
     347 * LOCHSTREIFEN_NO_ROW.
    296348 * @return the number of the special row, counting from zero.
    297349 **/
    298350int lochstreifen_get_highlight_row(LOCHSTREIFEN *l) {
    299         return (l->highlight_row_color == NULL) ? -1 : l->highlight_row_number;
     351        return l->highlight_row_number;
    300352}
    301353
     
    305357void lochstreifen_remove_highlight_row(LOCHSTREIFEN *l) {
    306358        //l->highlight_row_color = NULL;  /// nein, das ist dumm, weil es den highlight komplett entfernen würde.
    307         l->highlight_row_number = -1; // das ist schlau.
     359        l->highlight_row_number = LOCHSTREIFEN_NO_ROW; // das ist schlau.
    308360}
    309361
     
    332384 * row 2 to row 5).
    333385 **/
    334 void lochstreifen_set_highlight_bit(LOCHSTREIFEN *l, int number_of_row, int number_of_bit) {
     386void lochstreifen_set_highlight_bit(LOCHSTREIFEN *l, row_t number_of_row, track_t number_of_bit) {
    335387        l->highlight_bit_row = number_of_row;
    336388        l->highlight_bit_track = number_of_bit;
     
    344396 *
    345397 **/
    346 int lochstreifen_get_highlight_bit(LOCHSTREIFEN *l, int *number_of_row, int *number_of_bit) {
    347         if(l->highlight_bit_color == NULL)
     398int lochstreifen_get_highlight_bit(LOCHSTREIFEN *l, row_t *number_of_row, track_t *number_of_bit) {
     399        if(l->highlight_bit_row == LOCHSTREIFEN_NO_ROW)
    348400                return 0;
    349401        if(number_of_row != NULL)
     
    358410 **/
    359411void lochstreifen_remove_highlight_bit(LOCHSTREIFEN *l) {
    360         l->highlight_bit_color = NULL;
     412        //l->highlight_bit_color = NULL; // stupid.
     413        l->highlight_bit_row = LOCHSTREIFEN_NO_ROW; // more intelligent.
     414}
     415
     416/**
     417 * Whenever you change the matrix, call this function. It will just perform some
     418 * cleanup work, espacially calculate the inverse matrix for the other-side calculations.
     419 **/
     420void lochstreifen_check_matrix(LOCHSTREIFEN* l) {
     421        l->matrix_inverse = l->matrix; // copy matrix
     422        if(cairo_matrix_invert(&l->matrix_inverse) != CAIRO_STATUS_SUCCESS) { // invert the copy
     423                // there are some matrizes which are not invertable
     424                fprintf(stderr, "lochstreifen_check_matrix: Matrix is not invertable!\n");
     425        }
    361426}
    362427
     
    364429 * If you want LOCHSTREIFEN only to paint a small area from the whole papertape, this
    365430 * is the function you can call.
     431 * If you are using an affine transformation matrix for scaling/rotation/... purpose,
     432 * this function will automatically transform these values. So don't give here values
     433 * like "LOCHSTREIFEN_WIDTH" or "LOCHSTREIFEN_HEIGHT" ;-)
    366434 *
    367435 **/
     
    369437        if(l->clip == NULL)
    370438                l->clip = malloc(sizeof(cairo_rectangle_t));
     439
     440        cairo_matrix_transform_point(&l->matrix_inverse, &x, &y);
     441        cairo_matrix_transform_distance(&l->matrix_inverse, &width, &height);
    371442        l->clip->x = x;
    372443        l->clip->y = y;
     
    394465        printf("Scaling to length=%i, having length=%f, getting %f as scale factor\n",
    395466                length, LOCHSTREIFEN_LENGTH, scale_factor);
    396         cairo_matrix_scale(l->matrix, scale_factor, scale_factor);
     467        cairo_matrix_scale(&l->matrix, scale_factor, scale_factor);
     468        lochstreifen_check_matrix(l);
    397469}
    398470
    399471void lochstreifen_set_scaling_by_width(LOCHSTREIFEN *l, int width) {
    400472        double scale_factor = ((double)width) / LOCHSTREIFEN_WIDTH;
    401         cairo_matrix_scale(l->matrix, scale_factor, scale_factor);
     473        cairo_matrix_scale(&l->matrix, scale_factor, scale_factor);
     474        lochstreifen_check_matrix(l);
    402475}
    403476
    404477void lochstreifen_set_scaling_by_code_hole(LOCHSTREIFEN *l, int diameter) {
    405478        double scale_factor = ((double)diameter)/2 / LOCHSTREIFEN_RADIUS_CODE_HOLE;
    406         cairo_matrix_scale(l->matrix, scale_factor, scale_factor);
     479        cairo_matrix_scale(&l->matrix, scale_factor, scale_factor);
     480        lochstreifen_check_matrix(l);
    407481}
    408482
     
    429503        // transform the "bounding box" throught the matrix
    430504        for(i=0; i < (sizeof(x) / sizeof(double)); i++) {
    431                 cairo_matrix_transform_point(l->matrix, &x[i], &y[i]);
     505                cairo_matrix_transform_point(&l->matrix, &x[i], &y[i]);
    432506                // store biggest x/y values
    433507                if(width != NULL && x[i] > *width)
     
    459533
    460534/**
    461  * Get the row number from an x/y target cordinate. That is: At first, translate
     535 * Get a bit tuple from the positions on the target surface. This function
     536 * translates the points x/y with the inverse current translation matrix. Then
     537 * it calculates the row number that equals with the x coordinate and afterwards
     538 * the track number that equals with the y coordinate.
     539 *
     540 * If you need only one dimension, set the other NULL.
     541 *
     542 * You can use lochstreifen_get_traget_row_from_point and
     543 * lochstreifen_get_target_track_from_point if you need only one dimension. Furthermore
     544 * they will nicely return the requested data -- no need for call by reference.
     545 *
     546 * @param bit The target lochstreifen_bit_t (call by reference). Should not be NULL.
     547 * @param x  The x coordinate you want to check
     548 * @param y  The y coordinate you want to check
     549 **/
     550void lochstreifen_get_target_bit_from_point(LOCHSTREIFEN* l, row_t* row, track_t* track, double x, double y) {
     551        cairo_matrix_transform_point(&l->matrix_inverse, &x, &y); // transform points
     552       
     553        if(y < 0 || y > LOCHSTREIFEN_WIDTH) {
     554                // we are not at data, at all
     555                if(row != NULL)
     556                        *row = LOCHSTREIFEN_NO_ROW;
     557                if(track != NULL)
     558                        *track = LOCHSTREIFEN_NO_TRACK;
     559                return;
     560        }
     561       
     562        if(row == NULL) {
     563                // if only the track was requested, create a temporary row buffer, because
     564                // we need the row number as a basis for the correct track calculation.
     565                row_t row_buffer;
     566                row = &row_buffer;
     567        }
     568       
     569        // Row calculation is fairly easy:
     570        if(x < LOCHSTREIFEN_TEAR_OFF_LENGTH || x > (LOCHSTREIFEN_LENGTH - LOCHSTREIFEN_TEAR_OFF_LENGTH)) {
     571                // we are not at data
     572                *row = LOCHSTREIFEN_NO_ROW;
     573        } else {
     574                // getting the row from the x value. This is pretty much the same algorithm
     575                // like used in papertape_draw for checking up the rectangle bounding box (clipping).
     576                *row = floor(
     577                        (x - LOCHSTREIFEN_TEAR_OFF_LENGTH) / LOCHSTREIFEN_ROW_DISTANCE
     578                );
     579        }
     580       
     581        // Track calculation is much more complex:
     582        if(track != NULL) {
     583                /* get the track from the y value. This is not simply something like
     584                 *   *track = floor( y / LOCHSTREIFEN_TRACK_DISTANCE );
     585                 * because we must take care that a track is a round thing with a
     586                 * specific height.
     587                 */
     588                double M_x, M_y; // the centers of the circles
     589                int i; // some iterator
     590                // The center of this circle, fairly complex to calculate, see lochstreifen_draw.
     591                M_x = LOCHSTREIFEN_TEAR_OFF_LENGTH + (*row + 0.5) * LOCHSTREIFEN_ROW_DISTANCE;
     592                M_y = LOCHSTREIFEN_TRACK_DISTANCE; // the first track, to get onto papertape
     593                // this a genious canidate for loop unrolling:
     594                for(i=0; i < 8; i++) {
     595                        // simple linear algebra: Check if point is in the circle.
     596                        //fprintf(stderr, "bit %d: (%f|%f) <-> P(%f|%f) <= %f\n", i, M_x, M_y, x, y, LOCHSTREIFEN_RADIUS_CODE_HOLE);
     597                        if(hypot( (x-M_x) , (y-M_y) ) <= LOCHSTREIFEN_RADIUS_CODE_HOLE) {
     598                                // the point is in this circle, so we have found the correct track.
     599                                //fprintf(stderr, "FOUND %d\n", i);
     600                                *track = i;
     601                                return;
     602                        } else {
     603                                // go on, set M for next circle
     604                                M_y += LOCHSTREIFEN_TRACK_DISTANCE;
     605                                // jump over feed track before i == 3.
     606                                if(i == 2)
     607                                        M_y += LOCHSTREIFEN_TRACK_DISTANCE;
     608                        }
     609                } // for tracks
     610               
     611                // cursor not over circle:
     612                *track = LOCHSTREIFEN_NO_TRACK;
     613                //fprintf(stderr, "NOT FOUND TRACK.\n");
     614        } // y dimension
     615} // lochstreifen_get_target_bit_on_point
     616
     617/**
     618 * Get the row number from an x/y target coordinate. That is: At first, translate
    462619 * the points with the current translation matrix, afterwards calculate the row
    463620 * number for the position.
     
    465622 * @returns Row number, counting from zero. Negative value if point not on papertape data chunk.
    466623 **/
    467 int lochstreifen_get_target_row_from_point(LOCHSTREIFEN* l, double x, double y) {
    468         // transform points
    469         // zunächst ganz blöd: Matrix zur Laufzeit invertieren.
    470         cairo_matrix_t invert = *l->matrix; // copy matrix
    471         if(cairo_matrix_invert(&invert) != CAIRO_STATUS_SUCCESS) { // invert the copy
    472                 // there are some matrizes which are not invertable
    473                 fprintf(stderr, "lochstreifen_get_target_row_from_point: Matrix is not invertable!\n");
    474                 return -1;
    475         }
    476         cairo_matrix_transform_point(&invert, &x, &y); // transform points
    477 
    478         // now calculate position.
    479         // check if we are on data:
    480         if(y < 0 || y > LOCHSTREIFEN_WIDTH || x < LOCHSTREIFEN_TEAR_OFF_LENGTH || x > (LOCHSTREIFEN_LENGTH - LOCHSTREIFEN_TEAR_OFF_LENGTH))
    481                 return -2;
    482         // getting the row from the x value. This is pretty much the same algorithm
    483         // like used in papertape_draw for checking up the rectangle bounding box (clipping).
    484         return floor (
    485                 (x - LOCHSTREIFEN_TEAR_OFF_LENGTH) / LOCHSTREIFEN_ROW_DISTANCE
    486         );
    487        
     624row_t lochstreifen_get_target_row_from_point(LOCHSTREIFEN* l, double x, double y) {
     625        row_t row;
     626        lochstreifen_get_target_bit_from_point(l, &row, NULL, x, y);
     627        return row;
     628}
     629
     630track_t lochstreifen_get_target_track_from_point(LOCHSTREIFEN* l, double x, double y) {
     631        track_t track;
     632        lochstreifen_get_target_bit_from_point(l, NULL, &track, x, y);
     633        return track;
     634}
     635
     636
     637/**
     638 * Calculate the rectangle that contains the complete row on the LOCHSTREIFEN,
     639 * in target surface dimensions (using the transformation matrix). If the operation
     640 * fails (if the row doesn't exist), the rect is not touched at all.
     641 *
     642 * @param row Number of Row you want
     643 * @param rect Call by reference like rectangle type
     644 * @return LOCHSTREIFEN_SUCCESS or LOCHSTREIFEN_NO_ROW.
     645 **/
     646int lochstreifen_get_target_rect_from_row(LOCHSTREIFEN* l, row_t row, cairo_rectangle_t* rect) {
     647        // check wheter we are in bounds
     648        if(row < 0 || row > l->data_length)
     649                return LOCHSTREIFEN_NO_ROW;
     650
     651        // This rectangle is a bit bigger than the real track, so that outlines, etc.
     652        // could be drawn there, too.
     653       
     654        rect->x = LOCHSTREIFEN_TEAR_OFF_LENGTH + (row) * LOCHSTREIFEN_ROW_DISTANCE;
     655        rect->y = 0;
     656        rect->width = LOCHSTREIFEN_ROW_DISTANCE;
     657        rect->height = LOCHSTREIFEN_WIDTH;
     658       
     659        // take this as padding:
     660        #define TARGET_RECT_HOW_MUCH_BIGGER  (LOCHSTREIFEN_ROW_DISTANCE * 0.1)
     661        rect->x -= TARGET_RECT_HOW_MUCH_BIGGER;
     662        rect->y -= TARGET_RECT_HOW_MUCH_BIGGER;
     663        rect->width += 2*TARGET_RECT_HOW_MUCH_BIGGER;
     664        rect->height += 2*TARGET_RECT_HOW_MUCH_BIGGER;
     665       
     666        // transform the points
     667        cairo_matrix_transform_point(&l->matrix, &rect->x, &rect->y);
     668        cairo_matrix_transform_distance(&l->matrix, &rect->width, &rect->height);
     669       
     670        return LOCHSTREIFEN_SUCCESS;
     671}
     672
     673/**
     674 * This is just the same like lochstreifen_get_target_rect_from_row, just with
     675 * bits. This is still a rectangle which contains the complete circle that represents
     676 * the bit, useful e.g. for GDK expose events.
     677 *
     678 * @param row Number of Row
     679 * @param track Number of Track
     680 * @param rect Call by reference like rectangle type
     681 * @return LOCHSTREIFEN_SUCCESS or LOCHSTREIFEN_NO_ROW or LOCHSTREIFEN_NO_TRACK
     682 **/
     683int lochstreifen_get_target_rect_from_bit(LOCHSTREIFEN* l, row_t row, track_t track, cairo_rectangle_t* rect) {
     684        // check bounds
     685        if(row < 0 || row > l->data_length)
     686                return LOCHSTREIFEN_NO_ROW;
     687        if(track < 0 || track > 7)
     688                return LOCHSTREIFEN_NO_TRACK;
     689
     690        // the rectangle is doesn't touch the circle, but leaves quite a bit space around
     691        // it, so outlines, etc. should not be a problem.
     692
     693        // this code is quite like the beginning x/y dimensions in lochstreifen_draw():
     694        rect->x = LOCHSTREIFEN_TEAR_OFF_LENGTH + (row) * LOCHSTREIFEN_ROW_DISTANCE;
     695                  //+ (LOCHSTREIFEN_ROW_DISTANCE - LOCHSTREIFEN_RADIUS_CODE_HOLE*2) / 2; // the center
     696        rect->y = LOCHSTREIFEN_TRACK_DISTANCE * (track + (track > 2 ? 1 : 0) );
     697        // The correct values for width/height would be:
     698        //    rect->width = LOCHSTREIFEN_RADIUS_CODE_HOLE * 2;
     699        // but that won't at exposures if the hole is painted e.g. with an outline (cairo_stroke).
     700        // We therefore simply take the complete track as width
     701        rect->width = LOCHSTREIFEN_ROW_DISTANCE;
     702        rect->height = LOCHSTREIFEN_TRACK_DISTANCE * 2;
     703       
     704        // transform to user space
     705        cairo_matrix_transform_point(&l->matrix, &rect->x, &rect->y);
     706        cairo_matrix_transform_distance(&l->matrix, &rect->width, &rect->height);
     707       
     708        return LOCHSTREIFEN_SUCCESS;
    488709}
    489710
     
    524745                        //cairo_matrix_rotate();
    525746                case LOCHSTREIFEN_MOVEMENT_TO_RIGHT:
     747                       
    526748                case LOCHSTREIFEN_MOVEMENT_TO_BOTTOM:
    527                 case LOCHSTREIFEN_ROTATION_CLOCKWISE:
    528                 case LOCHSTREIFEN_ROTATION_ANTICLOCKWISE:
     749               
    529750                case LOCHSTREIFEN_MOVEMENT_NONE:
    530751                default:
    531752                        break;
    532753        }
     754        lochstreifen_check_matrix(l);
    533755}
    534756
     
    556778
    557779        // apply the matrix!
    558         cairo_set_matrix(cr, l->matrix);
    559        
     780        cairo_set_matrix(cr, &l->matrix);
     781       
     782        // check if we need to repaint the papertape
     783        if(l->clip != NULL && (l->clip->y > LOCHSTREIFEN_WIDTH || l->clip->x > LOCHSTREIFEN_LENGTH) ) {
     784                // Clipping region is outside of papertape!
     785                //printf("draw: Outside papertape.\n");
     786                return;
     787        }
    560788
    561789        // paint outer background color.
     
    575803                cairo_line_to(cr, LOCHSTREIFEN_TEAR_OFF_LENGTH, 0);
    576804                cairo_close_path(cr);
    577 
     805                cairo_fill(cr);
     806               
    578807                // long rectangular area over complete paper tape
    579                 cairo_rectangle(cr, LOCHSTREIFEN_TEAR_OFF_LENGTH, 0,
    580                         length - 2*LOCHSTREIFEN_TEAR_OFF_LENGTH, LOCHSTREIFEN_WIDTH);
     808                if(l->clip == NULL) {
     809                        cairo_rectangle(cr, LOCHSTREIFEN_TEAR_OFF_LENGTH, 0.0,
     810                                length - 2*LOCHSTREIFEN_TEAR_OFF_LENGTH, LOCHSTREIFEN_WIDTH);
     811                        // irc.gnome.org, #gtk+:
     812                        // <owen> sven__: a basic comment is that if you draw a *single* shape with cairo
     813                        // that's bigger than 32k pixels in any dimension, it's unlikely to work
     814                        // [17:51] <owen> sven__: for the Xlib backend. this is a lot more fixable now
     815                        // that Cairo switched to 24.8 fixed point internally, but I don't think anybody
     816                        // has done the work to fix it
     817                } else {
     818                        // calculate the neccessary width
     819                        // if clipping region exceeds lochstreifen width.... make it shorter, else let it.
     820                        double width = ( (l->clip->x + l->clip->width) > (LOCHSTREIFEN_LENGTH - LOCHSTREIFEN_TEAR_OFF_LENGTH) )
     821                                        ? ( LOCHSTREIFEN_LENGTH - LOCHSTREIFEN_TEAR_OFF_LENGTH - l->clip->x )
     822                                        : l->clip->width;
     823                        // don't have the clipping region paint in the tear off
     824                        // right, so crop it at the left.
     825                        if(l->clip->x < LOCHSTREIFEN_TEAR_OFF_LENGTH)
     826                                width -= LOCHSTREIFEN_TEAR_OFF_LENGTH;
     827                        cairo_rectangle(cr,
     828                                (l->clip->x >= LOCHSTREIFEN_TEAR_OFF_LENGTH) ?
     829                                        l->clip->x : LOCHSTREIFEN_TEAR_OFF_LENGTH,
     830                                0,
     831                                width,
     832                                LOCHSTREIFEN_WIDTH);
     833                }
     834                cairo_fill(cr);
     835               
    581836
    582837                // tear-off at the end (0.5 of paper tape width)
     
    587842                cairo_line_to(cr, length-LOCHSTREIFEN_TEAR_OFF_LENGTH * 0.2, 0);
    588843                cairo_close_path(cr);
    589 
    590                 // paper tape background finished.
    591844                cairo_fill(cr);
    592         }
     845               
     846        } // paper tape background finished.
    593847       
    594848        // paint feed holes in the tear-off at the beginning
     
    606860       
    607861        if(l->clip != NULL) {
    608                 // calculate clipping in dimension X (rows, bytes)
    609                 // calculation of first row to begin with.
    610                 row = floor (
    611                             (l->clip->x - LOCHSTREIFEN_TEAR_OFF_LENGTH - LOCHSTREIFEN_ROW_DISTANCE / 2)
    612                                               / LOCHSTREIFEN_ROW_DISTANCE
    613                 );
    614                
    615                 // calculation of last row to end with.
    616                 row_max = floor(
    617                      (length - (l->clip->x + l->clip->width) - LOCHSTREIFEN_TEAR_OFF_LENGTH - LOCHSTREIFEN_ROW_DISTANCE/2)
    618                                              / LOCHSTREIFEN_ROW_DISTANCE
    619                 );
    620 
    621                 // calculate clipping in dimension Y (tracks, bits)
     862                /* calculate clipping in dimension X (rows, bytes).
     863                 * Clipping in this dimension is very important, especially at very long
     864                 * papertapes. Application software (like GtkPaperTape) usually zooms the
     865                 * papertape, so it won't fit completely on the screen. So skipping bytes
     866                 * which are not displayed is very performant.
     867                 */
     868                if(l->clip->x < LOCHSTREIFEN_TEAR_OFF_LENGTH) {
     869                        // begin before tear off
     870                        row = 0;
     871                        row_max = floor(
     872                                ( l->clip->width - (l->clip->x - LOCHSTREIFEN_TEAR_OFF_LENGTH) )
     873                                / LOCHSTREIFEN_ROW_DISTANCE
     874                        );
     875                } else {
     876                        // after tear off
     877                        row = floor (
     878                                (l->clip->x - LOCHSTREIFEN_TEAR_OFF_LENGTH) / LOCHSTREIFEN_ROW_DISTANCE
     879                        );
     880                       
     881                        // end with just one more row as neccessary
     882                        row_max = row + 1 + ceil(
     883                                ( l->clip->width ) / LOCHSTREIFEN_ROW_DISTANCE
     884                        );
     885                }
     886               
     887                // don't go over the data range
     888                if(row_max > l->data_length)
     889                        row_max = l->data_length;
     890                // dont' have row_max smaller than row
     891                //if(row_max < row)
     892                //      row_max = row;
     893
     894                /* calculate clipping in dimension Y (tracks, bits)
     895                 * Y clipping is not as important, because there are only 9 circles
     896                 * to paint. The feed hole (which is painted just in the loop for the
     897                 * 3. track hole is not counted, therefore the calculations become somewhat
     898                 * inneccessary complex, compared to the painting overhead for the complete
     899                 * 8 tracks instead of e.g. only 6 tracks. Apart from that, application software
     900                 * usually doesn't clip the papertape this way, because users usually want to
     901                 * see a complete byte and not only a half byte.
     902                 */
    622903                // calculation of first track to begin with.
    623                 track_min = floor( l->clip->y / LOCHSTREIFEN_TRACK_DISTANCE );
     904                /*
     905                track_min = l->clip->y == 0 ? 0 : floor( l->clip->y / LOCHSTREIFEN_TRACK_DISTANCE );
     906               
    624907               
    625908                // calculation of last track to end with.
    626                 track_max = 8 - floor(
    627                          (LOCHSTREIFEN_WIDTH - (l->clip->y + l->clip->height))
    628                                  / LOCHSTREIFEN_TRACK_DISTANCE
    629                 );
     909                if(l->clip->y + l->clip->height > LOCHSTREIFEN_WIDTH)
     910                        track_max = 8; // clipping region is *much* bigger than the papertape width
     911                else {
     912                        // just paint one more than neccessary
     913                        track_max = 1 + 8 - floor(
     914                                (LOCHSTREIFEN_WIDTH - (l->clip->y + l->clip->height))
     915                                / LOCHSTREIFEN_TRACK_DISTANCE
     916                        );
     917                        // dont't go over the track range
     918                        if(track_max > 8)
     919                                track_max = 8;
     920                }*/
     921                track_min = 0;
     922                track_max = 8;
    630923        } else {
    631924                // no clipping. Paint *everything*.
     
    637930        }
    638931       
     932        if(l->clip != NULL) {
     933                double x,y,width,height;
     934                x=l->clip->x; y=l->clip->y; width=l->clip->width; height=l->clip->height;
     935                cairo_user_to_device(cr, &x, &y);
     936                cairo_user_to_device_distance(cr, &width, &height);
     937                printf("draw: %i|%i %ix%i ", (int)x, (int)y, (int)width, (int)height);
     938        } else    printf("draw: ");
     939        printf("row %i->%i track %i->%i\n", row, row_max, track_min, track_max);
     940       
    639941        // loop all the rows (bytes)
    640942        // x start: tear off + one half row offset + offset rows * length of row
    641         for(x=LOCHSTREIFEN_TEAR_OFF_LENGTH + LOCHSTREIFEN_TRACK_DISTANCE/2 + row*LOCHSTREIFEN_TRACK_DISTANCE;
    642             row < row_max; row++, x += LOCHSTREIFEN_TRACK_DISTANCE) {
    643        
     943        for(x=LOCHSTREIFEN_TEAR_OFF_LENGTH + LOCHSTREIFEN_ROW_DISTANCE/2 + row*LOCHSTREIFEN_ROW_DISTANCE;
     944            row < row_max; row++, x += LOCHSTREIFEN_ROW_DISTANCE) {
     945
     946                // call row callback
     947                if(l->row_callback != NULL) {
     948                        (*l->row_callback) (&row, cr, l->row_callback_user_data);
     949                        // at least now that's all the magic ;)
     950                }
     951               
    644952                // highlight region?
    645                 if(l->highlight_region_color != NULL &&
     953                if(l->highlight_region_color != NULL && l->highlight_region_start != LOCHSTREIFEN_NO_ROW &&
    646954                    (row >= l->highlight_region_start || row < l->highlight_region_end) ) {
    647955                        cairo_set_source(cr, l->highlight_region_color);
     
    650958                        // Rechteck? Wuerde zu den Löchern passen.
    651959                        // http://www.cairographics.org/cookbook/roundedrectangles/
    652                         cairo_rectangle(cr, x - LOCHSTREIFEN_TRACK_DISTANCE / 2, 0,
     960                        cairo_rectangle(cr, x - LOCHSTREIFEN_ROW_DISTANCE / 2, 0,
    653961                           LOCHSTREIFEN_TRACK_DISTANCE * (l->highlight_region_end - l->highlight_region_start),
    654962                           LOCHSTREIFEN_WIDTH);
     
    658966                // highlight (only) this row?
    659967                if(l->highlight_row_color != NULL && row == l->highlight_row_number) {
     968                        // if check again LOCHSTREIFEN_NO_ROW not neccessary because row iterator never
     969                        // gets LOCHSTREIFEN_NO_ROW.
    660970                        cairo_set_source(cr, l->highlight_row_color);
    661971                        // genauso abgerundetes Rechteck wie bei der region
    662972                        // überlegen.
    663                         cairo_rectangle(cr, x - LOCHSTREIFEN_TRACK_DISTANCE/2, 0,
     973                        cairo_rectangle(cr, x - LOCHSTREIFEN_ROW_DISTANCE/2, 0,
    664974                            LOCHSTREIFEN_TRACK_DISTANCE, LOCHSTREIFEN_WIDTH);
    665975                        cairo_fill(cr);
     
    6991009                        if(l->highlight_bit_row == row && l->highlight_bit_track == track
    7001010                           && l->highlight_bit_color != NULL) {
     1011                                // if check against l->highlight_bit_row == LOCHSTREIFEN_NO_ROW
     1012                                // not neccessary because row never gets LOCHSTREIFEN_NO_ROW.
     1013                               
    7011014                                // eigentlich wollen wir hier eine Umrahmung zeichnen,
    7021015                                // damit der Zustand (0/1) nicht unsichtbar wird. Jetzt
     
    7051018                                cairo_set_source(cr, l->highlight_bit_color);
    7061019                                cairo_arc(cr, x, y, LOCHSTREIFEN_RADIUS_CODE_HOLE, 0., 2*M_PI);
     1020                                cairo_set_line_width(cr, 0.01);
    7071021                                cairo_stroke(cr); // mal testen :-)
    7081022                        }
  • visualisator/lochstreifen.h

    r18 r19  
    1212typedef struct lochstreifen LOCHSTREIFEN;
    1313
     14/**
     15 * Identifing a track.
     16 * This enum is used in various functions.
     17 * Principally it's only sensefule for the
     18 * LOCHSTREIFEN_NO_TRACK value.
     19 **/
     20typedef enum lochstreifen_track {
     21        LOCHSTREIFEN_TRACK_0        = 0,
     22        LOCHSTREIFEN_TRACK_1        = 1,
     23        LOCHSTREIFEN_TRACK_2        = 2,
     24        LOCHSTREIFEN_TRACK_FEED     = -13,
     25        LOCHSTREIFEN_TRACK_3        = 3,
     26        LOCHSTREIFEN_TRACK_4        = 4,
     27        LOCHSTREIFEN_TRACK_5        = 5,
     28        LOCHSTREIFEN_TRACK_6        = 6,
     29        LOCHSTREIFEN_TRACK_7        = 7,
     30        LOCHSTREIFEN_NO_TRACK       = -42
     31} track_t;
     32
     33/**
     34 * This typedef just says: This int represents a row in a LOCHSTREIFEN
     35 * It's range should be >= 0 and <= the data_len member of the
     36 * LOCHSTREIFEN structure.
     37 * The MAX_INT value is therefore also the value of bytes which can be
     38 * drawn: 4 GB. That's pretty much, because it all must be held in RAM ;-)
     39 **/
     40typedef int row_t;
     41
     42/**
     43 * The adequate to the lochstreifen_track enum value LOCHSTREIFEN_NO_TRACK.
     44 * If a row_t == LOCHSTREIFEN_NO_ROW, it indicates that this
     45 * is not a row at all. Of course you could also simply use check if
     46 * row_t is < 0, but this is more meaningful.
     47 **/
     48#define LOCHSTREIFEN_NO_ROW  -1
     49
     50/**
     51 * To be used as a return value, in comparision with
     52 * LOCHSTREIFEN_NO_ROW and LOCHSTREIFEN_NO_TRACK: It indicates that
     53 * everything successed.
     54 **/
     55#define LOCHSTREIFEN_SUCCESS (-42*42)
     56
     57/**
     58 * This is the LOCHSTREIFEN structure. It will always be referenced as a
     59 * pointer, created by lochstreifen_new(). This function will also
     60 * initialize the LOCHSTREIFEN structure.
     61 * It's commonly referenced as "*l" or "l->", using "l" as abbrevation
     62 * for LOCHSTREIFEN.
     63 **/
    1464struct lochstreifen {
    1565        /* DATA (not supposed to be set directly) */
     
    2777
    2878        /// Highlighting a (row/byte) region
    29         int highlight_region_start; ///< counting from 0, already in selection
    30         int highlight_region_end;   ///< counting from 0, no more in selection
     79        row_t highlight_region_start; ///< counting from 0, already in selection
     80        row_t highlight_region_end;   ///< counting from 0, no more in selection
    3181        cairo_pattern_t *highlight_region_color; ///< == NULL => no selection painted
    3282
    3383        /// Highlight one special row
    34         int highlight_row_number;  ///< counting from 0
     84        row_t highlight_row_number;  ///< counting from 0
    3585        cairo_pattern_t *highlight_row_color;
    3686
    3787        /// Highlight one special bit (not complete track)
    38         int highlight_bit_row;     ///< counting from 0
    39         int highlight_bit_track;   ///< counting from 0
     88        row_t   highlight_bit_row;
     89        track_t highlight_bit_track;
    4090        cairo_pattern_t *highlight_bit_color;
    4191
     
    4494       
    4595        /// Matrix to apply for every paint process
    46         cairo_matrix_t *matrix;
     96        /// Call lochstreifen_check_matrix() after you have touched it.
     97        cairo_matrix_t matrix;
     98
     99        /// Callback functions:
     100        void (*row_callback) (const row_t* current_row, cairo_t* context, void* user_data);
     101        void* row_callback_user_data;
     102        //void (*bit_callback)
     103        // etc.
    47104
    48105        /*<private>*/
     
    51108        /// Make debug output if debug != 0.
    52109        byte_t debug;
     110       
     111        /// Inverse CTM. Don't touch it, use
     112        /// lochstreifen_check_matrix() instead to calculate it automatically
     113        cairo_matrix_t matrix_inverse;
    53114};
    54115
     
    61122#define LOCHSTREIFEN_DEFAULT_HIGHLIGHT_REGION_COLOR        cairo_pattern_create_rgb(0.95,  1, 0)
    62123#define LOCHSTREIFEN_DEFAULT_HIGHLIGHT_ROW_COLOR           cairo_pattern_create_rgb(1,     0, 0)
    63 #define LOCHSTREIFEN_DEFAULT_HIGHLIGHT_BIT_COLOR           cairo_pattern_create_rgb(0.4, 0.55, 0.7)
     124#define LOCHSTREIFEN_DEFAULT_HIGHLIGHT_BIT_COLOR           cairo_pattern_create_rgb(1,1,1)
     125#define LOCHSTREIFEN_DEFAULT_CTM                           { 1, 0, 0, 1, 0, 0 }
    64126
    65127/// dimensions of the paper tape after ECMA-10 standard
     
    90152                                           LOCHSTREIFEN_ROW_DISTANCE * (l->data_length + 1) )
    91153
    92 enum lochstreifen_direction {
     154typedef enum lochstreifen_direction {
    93155        // special values for compatibility to old implementation
    94156        LOCHSTREIFEN_MOVEMENT_TO_LEFT       = 0,
     
    99161        LOCHSTREIFEN_ROTATION_CLOCKWISE     = 4,
    100162        LOCHSTREIFEN_ROTATION_ANTICLOCKWISE = 5
    101 };
     163} lochstreifen_direction_t;
     164
     165
     166
    102167
    103168
    104169// functions
    105170LOCHSTREIFEN *lochstreifen_new();
     171LOCHSTREIFEN* lochstreifen_copy(const LOCHSTREIFEN* t);
     172void lochstreifen_free(LOCHSTREIFEN* l);
    106173void lochstreifen_print_debug(LOCHSTREIFEN* l);
    107174void lochstreifen_set_data(LOCHSTREIFEN *l, int data_length, byte_t *data);
     
    119186void lochstreifen_set_clip(LOCHSTREIFEN *l, double x, double y, double width, double height);
    120187void lochstreifen_remove_clip(LOCHSTREIFEN *l);
     188void lochstreifen_check_matrix(LOCHSTREIFEN* l);
    121189void lochstreifen_set_scaling_by_length(LOCHSTREIFEN *l, int length);
    122190void lochstreifen_set_scaling_by_width(LOCHSTREIFEN *l, int width);
     
    125193int lochstreifen_get_target_width(LOCHSTREIFEN *l);
    126194int lochstreifen_get_target_height(LOCHSTREIFEN *l);
    127 int lochstreifen_get_target_row_from_point(LOCHSTREIFEN* l, double x, double y);
     195void lochstreifen_get_target_bit_from_point(LOCHSTREIFEN* l, row_t* row, track_t* track, double x, double y);
     196row_t lochstreifen_get_target_row_from_point(LOCHSTREIFEN* l, double x, double y);
     197track_t lochstreifen_get_target_track_from_point(LOCHSTREIFEN* l, double x, double y);
     198int lochstreifen_get_target_rect_from_row(LOCHSTREIFEN* l, row_t row, cairo_rectangle_t* rect);
     199int lochstreifen_get_target_rect_from_bit(LOCHSTREIFEN* l, row_t row, track_t track, cairo_rectangle_t* rect);
    128200void lochstreifen_set_rotation(LOCHSTREIFEN *l, enum lochstreifen_direction direction);
    129201void lochstreifen_draw(LOCHSTREIFEN *l, cairo_t *cr);
Note: See TracChangeset for help on using the changeset viewer.
© 2008 - 2013 technikum29 • Sven Köppel • Some rights reserved
Powered by Trac
Expect where otherwise noted, content on this site is licensed under a Creative Commons 3.0 License