Index: trunk/src/board.c =================================================================== --- trunk/src/board.c (revision 27123) +++ trunk/src/board.c (revision 27124) @@ -367,3 +367,9 @@ return chg; } + +pcb_pixmap_t *pcb_pixmap_insert_or_free(pcb_board_t *pcb, pcb_pixmap_t *pm) +{ + +} + Index: trunk/src/pixmap.c =================================================================== --- trunk/src/pixmap.c (revision 27123) +++ trunk/src/pixmap.c (revision 27124) @@ -25,4 +25,95 @@ */ #include "config.h" + +#include +#include +#include + #include "pixmap.h" + +static unsigned long pm_next_uid = 0; + +static unsigned int pixmap_hash_(const void *key_, int pixels) +{ + pcb_pixmap_t *key = (pcb_pixmap_t *)key_; + unsigned int i; + + if (pixels && key->hash_valid) + return key->hash; + + i = longhash(key->sx); + i ^= longhash(key->sy); + i ^= longhash((long)(key->tr_rot * 1000.0) + (long)key->tr_xmirror * 2 + key->tr_ymirror); + if (pixels) { + i ^= jenhash(key->p, key->size); + key->hash = i; + key->hash_valid = 1; + } + else + i ^= longhash(key->neutral_uid); + return i; +} + +static unsigned int pixmap_hash_meta(const void *key) +{ + return pixmap_hash_(key, 0); +} + +static unsigned int pixmap_hash_pixels(const void *key) +{ + return pixmap_hash_(key, 1); +} + + +static int pixmap_eq_(const void *keya_, const void *keyb_, int pixels) +{ + const pcb_pixmap_t *keya = keya_, *keyb = keyb_; + if ((keya->transp_valid) || (keyb->transp_valid)) { + if (keya->transp_valid != keyb->transp_valid) + return 0; + if ((keya->tr != keyb->tr) || (keya->tg != keyb->tg) || (keya->tb != keyb->tb)) + return 0; + } + if ((keya->tr_xmirror != keyb->tr_xmirror) || (keya->tr_ymirror != keyb->tr_ymirror)) + return 0; + if (keya->tr_rot != keyb->tr_rot) + return 0; + if ((keya->sx != keyb->sx) || (keya->sy != keyb->sy)) + return 0; + if (pixels) + return (memcmp(keya->p, keyb->p, keya->size) == 0); + else + return (keya->neutral_uid == keyb->neutral_uid); +} + +static int pixmap_eq_meta(const void *keya, const void *keyb) +{ + return pixmap_eq_(keya, keyb, 0); +} + +static int pixmap_eq_pixels(const void *keya, const void *keyb) +{ + return pixmap_eq_(keya, keyb, 1); +} + + +void pcb_pixmap_hash_init(pcb_pixmap_hash_t *pmhash) +{ + htpp_init(&pmhash->meta, pixmap_hash_meta, pixmap_eq_meta); + htpp_init(&pmhash->pixels, pixmap_hash_pixels, pixmap_eq_pixels); +} + +void pcb_pixmap_hash_uninit(pcb_pixmap_hash_t *pmhash) +{ + htpp_uninit(&pmhash->meta); + htpp_uninit(&pmhash->pixels); +} + +pcb_pixmap_t *pcb_pixmap_insert_neutral_or_free(pcb_pixmap_hash_t *pmhash, pcb_pixmap_t *pm) +{ + if ((pm->tr_rot != 0) || pm->tr_xmirror || pm->tr_ymirror) + return NULL; + return NULL; +} + Index: trunk/src/pixmap.h =================================================================== --- trunk/src/pixmap.h (revision 27123) +++ trunk/src/pixmap.h (revision 27124) @@ -28,21 +28,22 @@ #define PCB_HID_PIXMAP_H #include "global_typedefs.h" +#include struct pcb_pixmap_s { - long size; /* total size in memory */ + long size; /* total size of the array in memory (sx*sy*3) */ long sx, sy; /* x and y dimensions */ unsigned char tr, tg, tb; /* color of the transparent pixel */ unsigned int hash; /* precalculated hash value */ unsigned char *p; /* pixel array in r,g,b rows of sx long each */ + unsigned long neutral_uid; /* UID of the pixmap in neutral position */ void *hid_data; /* HID's version of the pixmap */ /* transformation info */ - pcb_pixmap_t *neutral; /* NULL for pixmaps in neutral position; for transformed pixmaps reference back to the 'parent' */ pcb_angle_t tr_rot; /* rotation angle (0 if not transformed) */ - unsigned xmirror:1; /* whether the pixmap is mirrored along the x axis (vertical mirror) */ - unsigned ymirror:1; /* whether the pixmap is mirrored along the y axis (horizontal mirror) */ + unsigned tr_xmirror:1; /* whether the pixmap is mirrored along the x axis (vertical mirror) */ + unsigned tr_ymirror:1; /* whether the pixmap is mirrored along the y axis (horizontal mirror) */ unsigned transp_valid:1; /* 1 if transparent pixel is available */ unsigned hash_valid:1; /* 1 if the has value has been calculated */ @@ -49,5 +50,17 @@ unsigned hid_data_valid:1; /* 1 if hid_data is already generated and no data changed since - maintained by core, HIDs don't need to check */ }; +typedef struct pcb_pixmap_hash_s { + htpp_t meta; /* all pixmaps, hashed and compared only by metadata (including natural_uid) - used to look up a specific transformed version */ + htpp_t pixels; /* all pixmaps, hashed and compared by the pixels (but not natural_uid) - used to look up a specific pixel array */ +} pcb_pixmap_hash_t; +void pcb_pixmap_hash_init(pcb_pixmap_hash_t *pmhash); +void pcb_pixmap_hash_uninit(pcb_pixmap_hash_t *pmhash); + +/* Either inserts pm in the board's pixmap hash, if pm is new there, or frees + pm and returns the matching pixmap from the board's pixmap hash. pm must + be in neutral position (no rotation, no mirror). Returns NULL on error. */ +pcb_pixmap_t *pcb_pixmap_insert_neutral_or_free(pcb_pixmap_hash_t *pmhash, pcb_pixmap_t *pm); + #endif