449 lines
13 KiB
C
449 lines
13 KiB
C
/**
|
|
* $Id$
|
|
*
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* Contributor(s): Jiri Hnidek.
|
|
*
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
*/
|
|
|
|
#ifdef WITH_VERSE
|
|
|
|
#include <string.h>
|
|
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "DNA_listBase.h"
|
|
|
|
#include "BLI_dynamiclist.h"
|
|
#include "BLI_blenlib.h"
|
|
|
|
#include "BIF_verse.h"
|
|
|
|
#include "BKE_verse.h"
|
|
|
|
#include "verse.h"
|
|
|
|
/* function prototypes of static functions */
|
|
static void cb_b_dimension_set(void *user_data, VNodeID node_id, uint16 width, uint16 height, uint16 depth);
|
|
static void cb_b_layer_create(void *user_data, VNodeID node_id, VLayerID layer_id, const char *name, VNBLayerType type);
|
|
static void cb_b_layer_destroy(void *user_data, VNodeID node_id, VLayerID layer_id);
|
|
static void cb_b_tile_set(void *user_data, VNodeID node_id, VLayerID layer_id, uint16 tile_x, uint16 tile_y, uint16 z, VNBLayerType type, const VNBTile *tile);
|
|
|
|
static void change_layer_dimension(
|
|
VBitmapLayer *vblayer,
|
|
unsigned int old_width,
|
|
unsigned int old_height,
|
|
unsigned int t_old_width,
|
|
unsigned int t_old_height);
|
|
static void *alloc_verse_bitmap_layer_data(struct VBitmapLayer *vblayer);
|
|
|
|
/*
|
|
* resize/crop verse bitmap layer
|
|
*/
|
|
static void change_layer_dimension(
|
|
VBitmapLayer *vblayer,
|
|
unsigned int old_width,
|
|
unsigned int old_height,
|
|
unsigned int t_old_width,
|
|
unsigned int t_old_height)
|
|
{
|
|
struct VNode *vnode = vblayer->vnode;
|
|
unsigned int t_width = ((VBitmapData*)(vnode->data))->t_width;
|
|
unsigned int width = ((VBitmapData*)(vnode->data))->width;
|
|
unsigned int height = ((VBitmapData*)(vnode->data))->height;
|
|
unsigned int x, y, i, j;
|
|
|
|
i = j = 0;
|
|
|
|
/* "copy" old data to new data */
|
|
if(vblayer->type==VN_B_LAYER_UINT8) {
|
|
unsigned char *data = (unsigned char*)vblayer->data;
|
|
/* allocate new verse bitmap layer data */
|
|
unsigned char *new_data = (unsigned char*)alloc_verse_bitmap_layer_data(vblayer);
|
|
for(y=0; y<old_height && y<height; y++, i=y*t_width, j=y*t_old_width) {
|
|
for(x=0; x<old_width && y<width; x++, i++, j++) {
|
|
new_data[i] = data[j];
|
|
}
|
|
}
|
|
MEM_freeN(vblayer->data);
|
|
vblayer->data = new_data;
|
|
}
|
|
}
|
|
|
|
/*
|
|
* free data stored in verse bitmap layer
|
|
*/
|
|
void free_bitmap_layer_data(VBitmapLayer *vblayer)
|
|
{
|
|
struct VerseSession *session = vblayer->vnode->session;
|
|
|
|
/* free name of bitmap layer */
|
|
MEM_freeN(vblayer->name);
|
|
|
|
/* unsubscribe from verse bitmap layer */
|
|
if(session->flag & VERSE_CONNECTED)
|
|
verse_send_b_layer_unsubscribe(vblayer->vnode->id, vblayer->id);
|
|
|
|
/* free image data of bitmap layer */
|
|
if(vblayer->data) MEM_freeN(vblayer->data);
|
|
}
|
|
|
|
/*
|
|
* allocate data of verse bitmap layer
|
|
*/
|
|
static void *alloc_verse_bitmap_layer_data(VBitmapLayer *vblayer)
|
|
{
|
|
struct VNode *vnode = vblayer->vnode;
|
|
unsigned int t_width = ((VBitmapData*)(vnode->data))->t_width;
|
|
unsigned int t_height = ((VBitmapData*)(vnode->data))->t_height;
|
|
unsigned int size;
|
|
void *data;
|
|
|
|
size = t_width*t_height;
|
|
|
|
/* allocation of own data stored in verse bitmap layer */
|
|
switch (vblayer->type) {
|
|
case VN_B_LAYER_UINT1:
|
|
data = (void*)MEM_mallocN(sizeof(unsigned char)*size, "VBLayer data uint1");
|
|
break;
|
|
case VN_B_LAYER_UINT8:
|
|
data = (void*)MEM_mallocN(sizeof(unsigned char)*size, "VBLayer data uint8");
|
|
break;
|
|
case VN_B_LAYER_UINT16:
|
|
data = (void*)MEM_mallocN(sizeof(unsigned int)*size, "VBLayer data uint16");
|
|
break;
|
|
case VN_B_LAYER_REAL32:
|
|
data = (void*)MEM_mallocN(sizeof(float)*size, "VBLayer data float16");
|
|
break;
|
|
case VN_B_LAYER_REAL64:
|
|
data = (void*)MEM_mallocN(sizeof(double)*size, "VBLayer data float32");
|
|
break;
|
|
default:
|
|
data = NULL;
|
|
break;
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
/*
|
|
* create verse bitmap layer
|
|
*/
|
|
VBitmapLayer *create_bitmap_layer(
|
|
VNode *vnode,
|
|
VLayerID layer_id,
|
|
const char *name,
|
|
VNBLayerType type)
|
|
{
|
|
struct VBitmapLayer *vblayer;
|
|
unsigned int width = ((VBitmapData*)(vnode->data))->width;
|
|
unsigned int height = ((VBitmapData*)(vnode->data))->height;
|
|
|
|
/* allocate memory for own verse bitmap layer */
|
|
vblayer = (VBitmapLayer*)MEM_mallocN(sizeof(VBitmapLayer), "Verse Bitmap Layer");
|
|
|
|
/* verse bitmap layer will include pointer at parent verse node and own id */
|
|
vblayer->vnode = vnode;
|
|
vblayer->id = layer_id;
|
|
|
|
/* name of verse layer */
|
|
vblayer->name = (char*)MEM_mallocN(sizeof(char)*(strlen(name)+1), "Verse Bitmap Layer name");
|
|
vblayer->name[0] = '\0';
|
|
strcpy(vblayer->name, name);
|
|
|
|
/* type of data stored in verse bitmap layer */
|
|
vblayer->type = type;
|
|
|
|
/* we can allocate memory for layer data, when we know dimmension of layers; when
|
|
* we don't know it, then we will allocate this data when we will receive dimmension */
|
|
if(width==0 || height==0)
|
|
vblayer->data = NULL;
|
|
else
|
|
vblayer->data = alloc_verse_bitmap_layer_data(vblayer);
|
|
|
|
vblayer->flag = 0;
|
|
|
|
return vblayer;
|
|
}
|
|
|
|
/*
|
|
* free data of bitmap node
|
|
*/
|
|
void free_bitmap_node_data(VNode *vnode)
|
|
{
|
|
if(vnode->data) {
|
|
struct VBitmapLayer *vblayer = (VBitmapLayer*)((VBitmapData*)(vnode->data))->layers.lb.first;
|
|
|
|
/* free all VerseLayer data */
|
|
while(vblayer) {
|
|
free_bitmap_layer_data(vblayer);
|
|
vblayer = vblayer->next;
|
|
}
|
|
|
|
/* free all VerseLayers */
|
|
BLI_dlist_destroy(&(((VGeomData*)vnode->data)->layers));
|
|
}
|
|
}
|
|
|
|
/*
|
|
* create data of bitmap node
|
|
*/
|
|
VBitmapData *create_bitmap_data()
|
|
{
|
|
struct VBitmapData *vbitmap;
|
|
|
|
vbitmap = (VBitmapData*)MEM_mallocN(sizeof(VBitmapData), "Verse Bitmap Data");
|
|
|
|
BLI_dlist_init(&(vbitmap->layers));
|
|
vbitmap->queue.first = vbitmap->queue.last = NULL;
|
|
|
|
vbitmap->width = 0;
|
|
vbitmap->height = 0;
|
|
vbitmap->depth = 0;
|
|
|
|
vbitmap->image = NULL;
|
|
|
|
vbitmap->post_bitmap_dimension_set = post_bitmap_dimension_set;
|
|
vbitmap->post_bitmap_layer_create = post_bitmap_layer_create;
|
|
vbitmap->post_bitmap_layer_destroy = post_bitmap_layer_destroy;
|
|
vbitmap->post_bitmap_tile_set = post_bitmap_tile_set;
|
|
|
|
return vbitmap;
|
|
}
|
|
|
|
/*
|
|
* callback function, dimension of image was changed, it is neccessary to
|
|
* crop all layers
|
|
*/
|
|
static void cb_b_dimension_set(
|
|
void *user_data,
|
|
VNodeID node_id,
|
|
uint16 width,
|
|
uint16 height,
|
|
uint16 depth)
|
|
{
|
|
struct VerseSession *session = (VerseSession*)current_verse_session();
|
|
struct VNode *vnode;
|
|
struct VBitmapLayer *vblayer;
|
|
unsigned int old_width, old_height, t_old_width, t_old_height;
|
|
|
|
if(!session) return;
|
|
|
|
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
|
|
if(!vnode) return;
|
|
|
|
#ifdef VERSE_DEBUG_PRINT
|
|
printf("\t cb_b_dimension_set()\n");
|
|
#endif
|
|
|
|
/* backup old width and height */
|
|
old_width = ((VBitmapData*)(vnode->data))->width;
|
|
old_height = ((VBitmapData*)(vnode->data))->height;
|
|
t_old_width = ((VBitmapData*)(vnode->data))->t_width;
|
|
t_old_height = ((VBitmapData*)(vnode->data))->t_height;
|
|
|
|
/* set up new dimension of layers */
|
|
((VBitmapData*)(vnode->data))->width = width;
|
|
((VBitmapData*)(vnode->data))->height = height;
|
|
((VBitmapData*)(vnode->data))->depth = depth;
|
|
|
|
/* we cache t_width because tiles aren't one pixel width */
|
|
if((width % VN_B_TILE_SIZE)!=0)
|
|
((VBitmapData*)(vnode->data))->t_width = (width/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE;
|
|
else
|
|
((VBitmapData*)(vnode->data))->t_width = width;
|
|
|
|
/* we cache t_height because tiles aren't one pixel height */
|
|
if((height % VN_B_TILE_SIZE)!=0)
|
|
((VBitmapData*)(vnode->data))->t_height = (height/VN_B_TILE_SIZE + 1)*VN_B_TILE_SIZE;
|
|
else
|
|
((VBitmapData*)(vnode->data))->t_height = height;
|
|
|
|
/* crop resize all layers */
|
|
vblayer = ((VBitmapData*)vnode->data)->layers.lb.first;
|
|
|
|
while(vblayer) {
|
|
/* when this callback function received after cb_b_layer_create,
|
|
* then we have to allocate memory for verse bitmap layer data */
|
|
if(!vblayer->data) vblayer->data = alloc_verse_bitmap_layer_data(vblayer);
|
|
/* crop/resize all verse bitmap layers */
|
|
else change_layer_dimension(vblayer, old_width, old_height, t_old_width, t_old_height);
|
|
|
|
vblayer = vblayer->next;
|
|
}
|
|
|
|
/* post callback function */
|
|
((VBitmapData*)(vnode->data))->post_bitmap_dimension_set(vnode);
|
|
}
|
|
|
|
/*
|
|
* callback function, new layer channel of image was created
|
|
*/
|
|
static void cb_b_layer_create(
|
|
void *user_data,
|
|
VNodeID node_id,
|
|
VLayerID layer_id,
|
|
const char *name,
|
|
VNBLayerType type)
|
|
{
|
|
struct VerseSession *session = (VerseSession*)current_verse_session();
|
|
struct VNode *vnode;
|
|
struct VBitmapLayer *vblayer;
|
|
|
|
if(!session) return;
|
|
|
|
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
|
|
if(!vnode) return;
|
|
|
|
#ifdef VERSE_DEBUG_PRINT
|
|
printf("\t cb_b_layer_create()\n");
|
|
#endif
|
|
|
|
/* when no layer exists, then new layer will be created */
|
|
vblayer = create_bitmap_layer(vnode, layer_id, name, type);
|
|
|
|
/* add verse bitmap layer to list of layers */
|
|
BLI_dlist_add_item_index(&((VBitmapData*)vnode->data)->layers, vblayer, layer_id);
|
|
|
|
/* post callback function */
|
|
((VBitmapData*)(vnode->data))->post_bitmap_layer_create(vblayer);
|
|
|
|
}
|
|
|
|
/*
|
|
* callback function, existing layer of image was destroyed
|
|
*/
|
|
static void cb_b_layer_destroy(
|
|
void *user_data,
|
|
VNodeID node_id,
|
|
VLayerID layer_id)
|
|
{
|
|
struct VerseSession *session = (VerseSession*)current_verse_session();
|
|
struct VNode *vnode;
|
|
struct VBitmapLayer *vblayer;
|
|
|
|
if(!session) return;
|
|
|
|
/* find node of this layer*/
|
|
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
|
|
if(!vnode) return;
|
|
|
|
vblayer = (VBitmapLayer*)BLI_dlist_find_link(&(((VBitmapData*)vnode->data)->layers), layer_id);
|
|
if(!vblayer) return;
|
|
|
|
#ifdef VERSE_DEBUG_PRINT
|
|
printf("\t cb_b_layer_destroy()\n");
|
|
#endif
|
|
|
|
/* remove verse bitmap layer from list of layers */
|
|
BLI_dlist_rem_item(&(((VBitmapData*)vnode->data)->layers), layer_id);
|
|
|
|
/* post callback function */
|
|
((VBitmapData*)(vnode->data))->post_bitmap_layer_destroy(vblayer);
|
|
|
|
/* free data of verse bitmap layer */
|
|
free_bitmap_layer_data(vblayer);
|
|
|
|
/* free verse bitmap layer */
|
|
MEM_freeN(vblayer);
|
|
}
|
|
|
|
/*
|
|
* callback function, small part (8x8 pixels) was changed
|
|
*/
|
|
static void cb_b_tile_set(
|
|
void *user_data,
|
|
VNodeID node_id,
|
|
VLayerID layer_id,
|
|
uint16 tile_x,
|
|
uint16 tile_y,
|
|
uint16 z,
|
|
VNBLayerType type,
|
|
const VNBTile *tile)
|
|
{
|
|
struct VerseSession *session = (VerseSession*)current_verse_session();
|
|
struct VNode *vnode;
|
|
struct VBitmapLayer *vblayer;
|
|
unsigned int x, y, xs, ys, width, height, t_height, t_width, i, j;
|
|
|
|
if(!session) return;
|
|
|
|
/* try to find verse node in dynamic list nodes */
|
|
vnode = (VNode*)BLI_dlist_find_link(&(session->nodes), (unsigned int)node_id);
|
|
if(!vnode) return;
|
|
|
|
/* try to find verse bitmap layer in list of layers */
|
|
vblayer = (VBitmapLayer*)BLI_dlist_find_link(&(((VBitmapData*)vnode->data)->layers), layer_id);
|
|
if(!vblayer) return;
|
|
|
|
/* we have to have allocated memory for bitmap layer */
|
|
if(!vblayer->data) return;
|
|
|
|
width = ((VBitmapData*)vnode->data)->width;
|
|
height = ((VBitmapData*)vnode->data)->height;
|
|
|
|
/* width of verse image including all tiles */
|
|
t_height = ((VBitmapData*)vnode->data)->t_height;
|
|
/* height of verse image including all tiles */
|
|
t_width = ((VBitmapData*)vnode->data)->t_width;
|
|
|
|
#ifdef VERSE_DEBUG_PRINT
|
|
printf("\t cb_b_tile_set()\n");
|
|
#endif
|
|
|
|
xs = tile_x*VN_B_TILE_SIZE;
|
|
ys = tile_y*VN_B_TILE_SIZE;
|
|
|
|
/* initial position in one dimension vblayer->data (y_start*width + x_start) */
|
|
i = ys*t_width + xs;
|
|
/* intial position in one dimension tile array */
|
|
j = 0;
|
|
|
|
if(type==VN_B_LAYER_UINT8) {
|
|
unsigned char *data = (unsigned char*)vblayer->data;
|
|
for(y=ys; y<ys+VN_B_TILE_SIZE && y<height; y++, i=y*t_width+xs)
|
|
for(x=xs; x<xs+VN_B_TILE_SIZE && x<width; x++, i++, j++)
|
|
data[i] = (unsigned char)tile->vuint8[j];
|
|
}
|
|
|
|
/* post callback function */
|
|
((VBitmapData*)(vnode->data))->post_bitmap_tile_set(vblayer, xs, ys);
|
|
}
|
|
|
|
/*
|
|
* set up all callbacks functions for image nodes
|
|
*/
|
|
void set_bitmap_callbacks(void)
|
|
{
|
|
/* dimension (size) of bitmap was set up or changes (image will be croped) */
|
|
verse_callback_set(verse_send_b_dimensions_set, cb_b_dimension_set, NULL);
|
|
|
|
/* new layer (chanell) of image was added or created */
|
|
verse_callback_set(verse_send_b_layer_create, cb_b_layer_create, NULL);
|
|
|
|
/* existing layer was destroyed */
|
|
verse_callback_set(verse_send_b_layer_destroy, cb_b_layer_destroy, NULL);
|
|
|
|
/* some tile (small part 8x8 pixels of image was changed) */
|
|
verse_callback_set(verse_send_b_tile_set, cb_b_tile_set, NULL);
|
|
}
|
|
|
|
#endif
|
|
|