Skip to content

Commit

Permalink
Added transparent avatars. Required changing all image functions. This
Browse files Browse the repository at this point in the history
breaks images on android.
  • Loading branch information
Doom032 committed Jan 14, 2015
1 parent e2eb01b commit 15961b1
Show file tree
Hide file tree
Showing 17 changed files with 441 additions and 195 deletions.
21 changes: 17 additions & 4 deletions android/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,22 @@ void postmessage(uint32_t msg, uint16_t param1, uint16_t param2, void *data)
write(pipefd[1], &piping, sizeof(PIPING));
}

void image_set_filter(UTOX_NATIVE_IMAGE *image, uint8_t filter)
{
}

void image_set_scale(UTOX_NATIVE_IMAGE *image, double scale)
{
}

void draw_image(const UTOX_NATIVE_IMAGE *image, int x, int y, uint32_t width, uint32_t height, uint32_t imgx, uint32_t imgy)
{
}


/* this function is no longer used, but it might contain handy information for creating the newer image draw functions
on android. Currently drawing images is unsupported.
void drawimage(UTOX_NATIVE_IMAGE data, int x, int y, int width, int height, int maxwidth, _Bool zoom, double position)
{
GLuint texture = data;
Expand All @@ -81,10 +97,7 @@ void drawimage(UTOX_NATIVE_IMAGE data, int x, int y, int width, int height, int
glUniform3fv(k2, 1, one);
}

void drawavatarimage(UTOX_NATIVE_IMAGE data, int x, int y, int width, int height, int targetwidth, int targetheight)
{
}
*/

void thread(void func(void*), void *args)
{
Expand Down
14 changes: 13 additions & 1 deletion avatar.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,14 @@ int set_avatar(AVATAR *avatar, const uint8_t *data, uint32_t size, _Bool create_
}

uint16_t w, h;
UTOX_NATIVE_IMAGE image = png_to_image((UTOX_PNG_IMAGE)data, size, &w, &h);
UTOX_NATIVE_IMAGE *image = png_to_image((UTOX_PNG_IMAGE)data, size, &w, &h, 1);
if(!UTOX_NATIVE_IMAGE_IS_VALID(image)) {
debug("warning: avatar is invalid\n");
return 0;
} else {

avatar_free_image(avatar);

avatar->image = image;
avatar->width = w;
avatar->height = h;
Expand All @@ -148,6 +151,15 @@ int set_avatar(AVATAR *avatar, const uint8_t *data, uint32_t size, _Bool create_
void unset_avatar(AVATAR *avatar)
{
avatar->format = TOX_AVATAR_FORMAT_NONE;
avatar_free_image(avatar);
}

void avatar_free_image(AVATAR *avatar)
{
if (avatar->image) {
image_free(avatar->image);
avatar->image = NULL;
}
}

/* sets self avatar, see self_set_and_save_avatar */
Expand Down
8 changes: 6 additions & 2 deletions avatar.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
typedef struct avatar {
uint8_t format; /* one of TOX_AVATAR_FORMAT */
uint8_t hash[TOX_HASH_LENGTH]; /* tox_hash for the png data of this avatar */
UTOX_NATIVE_IMAGE image; /* converted avatar image to draw */
UTOX_NATIVE_IMAGE *image; /* converted avatar image to draw */
uint16_t width, height; /* width and height of image (in pixels) */
}AVATAR;

Expand Down Expand Up @@ -71,9 +71,13 @@ int delete_avatar_hash(const char_t *id);
*/
int set_avatar(AVATAR *avatar, const uint8_t *data, uint32_t size, _Bool create_hash);

/* unsets an avatar by setting its format to TOX_AVATAR_FORMAT_NONE */
/* unsets an avatar by setting its format to TOX_AVATAR_FORMAT_NONE and
* freeing its image */
void unset_avatar(AVATAR *avatar);

/* frees the image of an avatar, does nothing if image is NULL */
void avatar_free_image(AVATAR *avatar);

/* sets own avatar based on given png data and saves it to disk if successful
* data is png data to set avatar to
* size is size of data
Expand Down
4 changes: 2 additions & 2 deletions friend.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ void friend_setname(FRIEND *f, char_t *name, STRING_IDX length)
f->name[f->name_length] = 0;
}

void friend_sendimage(FRIEND *f, UTOX_NATIVE_IMAGE native_image, uint16_t width, uint16_t height, UTOX_PNG_IMAGE png_image, size_t png_size)
void friend_sendimage(FRIEND *f, UTOX_NATIVE_IMAGE *native_image, uint16_t width, uint16_t height, UTOX_PNG_IMAGE png_image, size_t png_size)
{
MSG_IMG *msg = malloc(sizeof(MSG_IMG));
msg->author = 1;
Expand All @@ -50,7 +50,7 @@ void friend_sendimage(FRIEND *f, UTOX_NATIVE_IMAGE native_image, uint16_t width,
void friend_recvimage(FRIEND *f, UTOX_PNG_IMAGE png_image, size_t png_size)
{
uint16_t width, height;
UTOX_NATIVE_IMAGE native_image = png_to_image(png_image, png_size, &width, &height);
UTOX_NATIVE_IMAGE *native_image = png_to_image(png_image, png_size, &width, &height, 0);
if(!UTOX_NATIVE_IMAGE_IS_VALID(native_image)) {
return;
}
Expand Down
2 changes: 1 addition & 1 deletion friend.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ typedef struct groupchat {

void friend_setname(FRIEND *f, char_t *name, STRING_IDX length);
void friend_addmessage(FRIEND *f, void *data);
void friend_sendimage(FRIEND *f, UTOX_NATIVE_IMAGE, uint16_t width, uint16_t height, UTOX_PNG_IMAGE, size_t png_size);
void friend_sendimage(FRIEND *f, UTOX_NATIVE_IMAGE *, uint16_t width, uint16_t height, UTOX_PNG_IMAGE, size_t png_size);
void friend_recvimage(FRIEND *f, UTOX_PNG_IMAGE, size_t png_size);

void friend_notify(FRIEND *f, char_t *str, STRING_IDX str_length, char_t *msg, STRING_IDX msg_length);
Expand Down
2 changes: 1 addition & 1 deletion list.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ static void drawitem(ITEM *i, int UNUSED(x), int y)

// draw avatar or default image
if (friend_has_avatar(f)) {
drawavatarimage(f->avatar.image, LIST_AVATAR_X, y + LIST_AVATAR_Y, f->avatar.width, f->avatar.height, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH);
draw_avatar_image(f->avatar.image, LIST_AVATAR_X, y + LIST_AVATAR_Y, f->avatar.width, f->avatar.height, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH);
} else {
drawalpha(BM_CONTACT, LIST_AVATAR_X, y + LIST_AVATAR_Y, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH, (sitem == i) ? LIST_MAIN : WHITE);
}
Expand Down
33 changes: 23 additions & 10 deletions main.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,17 +219,30 @@ void loadalpha(int bm, void *data, int width, int height);
void desktopgrab(_Bool video);
void notify(char_t *title, STRING_IDX title_length, char_t *msg, STRING_IDX msg_length);
void setscale(void);
void drawimage(UTOX_NATIVE_IMAGE, int x, int y, int width, int height, int maxwidth, _Bool zoom, double position);

/* draws an image in the style of an avatar at within rect (x,y,targetwidth,targetheight)
* this means: resize the image while keeping proportion so that the dimension(width or height) that has the smallest rational difference to the targetdimension becomes exactly targetdimension, then
* crop the image so it fits in the (x,y,targetwidth,targetheight) rect, and
* set the position if a dimension is too large so it's centered on the middle
*
* first argument is the image to draw, width and height are the width and height of the input image

enum {
FILTER_NEAREST, // ugly and quick filtering
FILTER_BILINEAR // prettier and a bit slower filtering
};
/* set filtering method used when resizing given image to one of above enum */
void image_set_filter(UTOX_NATIVE_IMAGE *image, uint8_t filter);

/* set scale of image so that when it's drawn it will be `scale' times as large(2.0 for double size, 0.5 for half, etc.)
* notes: theoretically lowest possible scale is (1.0/65536.0), highest is 65536.0, values outside of this range will create weird issues
* scaling will be rounded to pixels, so it might not be exact
*/
void drawavatarimage(UTOX_NATIVE_IMAGE, int x, int y, int width, int height, int targetwidth, int targetheight);
UTOX_NATIVE_IMAGE png_to_image(const UTOX_PNG_IMAGE, size_t png_size, uint16_t *w, uint16_t *h);
void image_set_scale(UTOX_NATIVE_IMAGE *image, double scale);

/* draws an utox image with or without alpha channel into the rect of (x,y,width,height) on the screen,
* starting at position (imgx,imgy) of the image */
void draw_image(const UTOX_NATIVE_IMAGE *image, int x, int y, uint32_t width, uint32_t height, uint32_t imgx, uint32_t imgy);

/* converts a png to a UTOX_NATIVE_IMAGE, returns a pointer to it, keeping alpha channel only if keep_alpha is 1 */
UTOX_NATIVE_IMAGE *png_to_image(const UTOX_PNG_IMAGE, size_t size, uint16_t *w, uint16_t *h, _Bool keep_alpha);

/* free an image created by png_to_image */
void image_free(UTOX_NATIVE_IMAGE *image);

void showkeyboard(_Bool show);
void redraw(void);
void update_tray(void);
Expand Down
34 changes: 30 additions & 4 deletions messages.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,29 @@ static FRIEND* get_typers(MESSAGES *m) {
return NULL;
}

/* draws an inline image at rect (x,y,width,height)
* maxwidth is maximum width the image can take in
* zoom is whether the image is currently zoomed in
* position is the y position along the image the player has scrolled */
static void draw_message_image(UTOX_NATIVE_IMAGE *image, int x, int y, uint32_t width, uint32_t height, uint32_t maxwidth, _Bool zoom, double position)
{
if(!zoom && width > maxwidth) {
image_set_scale(image, (double)maxwidth / width);
image_set_filter(image, FILTER_BILINEAR);

draw_image(image, x, y, maxwidth, height * maxwidth / width, 0, 0);

image_set_scale(image, 1.0);
image_set_filter(image, FILTER_NEAREST);
} else {
if(width > maxwidth) {
draw_image(image, x, y, maxwidth, height, (int)((double)(width - maxwidth) * position), 0);
} else {
draw_image(image, x, y, width, height, 0, 0);
}
}
}

/** Formats all messages from self and friends, and then call draw functions
* to write them to the UI.
*
Expand Down Expand Up @@ -126,7 +149,7 @@ void messages_draw(MESSAGES *m, int x, int y, int width, int height)
/* image */
MSG_IMG *img = (void*)msg;
int maxwidth = width - MESSAGES_X - TIME_WIDTH;
drawimage(img->image, x + MESSAGES_X, y, img->w, img->h, maxwidth, img->zoom, img->position);
draw_message_image(img->image, x + MESSAGES_X, y, img->w, img->h, maxwidth, img->zoom, img->position);
y += (img->zoom || img->w <= maxwidth) ? img->h : img->h * maxwidth / img->w;
break;
}
Expand Down Expand Up @@ -958,13 +981,16 @@ _Bool messages_char(uint32_t ch)
void message_free(MESSAGE *msg)
{
switch(msg->msg_type) {
case MSG_TYPE_IMAGE:
//TODO: freeimage
case MSG_TYPE_IMAGE: {
MSG_IMG *img = (void*)msg;
image_free(img->image);
break;
case MSG_TYPE_FILE:
}
case MSG_TYPE_FILE: {
//already gets free()d
//free(((MSG_FILE*)msg)->path);
break;
}
}
free(msg);
}
2 changes: 1 addition & 1 deletion messages.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ typedef struct {
uint16_t w, h;
_Bool zoom;
double position;
UTOX_NATIVE_IMAGE image;
UTOX_NATIVE_IMAGE *image;
} MSG_IMG;

typedef struct msg_file {
Expand Down
2 changes: 1 addition & 1 deletion tox.c
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,7 @@ static void set_callbacks(Tox *tox)
utox_set_callbacks_for_transfer(tox);
}

/* tried to load avatar from disk for given client id string and set avatar based on its result
/* tries to load avatar from disk for given client id string and set avatar based on saved png data
* avatar is avatar to initialize. Will be unset if no file is found on disk or if file is corrupt or too large,
* otherwise will be set to avatar found on disk
* id is cid string of whose avatar to find(see also load_avatar in avatar.h)
Expand Down
26 changes: 22 additions & 4 deletions ui.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,33 @@ _Bool maybe_i18nal_string_is_valid(MAYBE_I18NAL_STRING *mis) {

/***** MAYBE_I18NAL_STRING helpers end *****/

void draw_avatar_image(UTOX_NATIVE_IMAGE *image, int x, int y, uint32_t width, uint32_t height, uint32_t targetwidth, uint32_t targetheight)
{
/* get smallest difference of width or height */
double scale = (abs((int)width - targetwidth) > abs((int)height - targetheight)) ?
(double)targetheight / height :
(double)targetwidth / width;

image_set_scale(image, scale);
image_set_filter(image, FILTER_BILINEAR);

/* set position to show the middle of the image in the center */
int xpos = (int) ((double)width * scale / 2 - (double)targetwidth / 2);
int ypos = (int) ((double)height * scale / 2 - (double)targetheight / 2);

draw_image(image, x, y, targetwidth, targetheight, xpos, ypos);

image_set_scale(image, 1.0);
image_set_filter(image, FILTER_NEAREST);
}

uint32_t status_color[] = {
C_GREEN,
C_YELLOW,
C_RED,
C_RED
};

/* Draw funcitons to generate Window pages */

/* Top left self interface Avatar, name, statusmsg, status icon */
static void drawself(void)
{
Expand All @@ -58,7 +76,7 @@ static void drawself(void)

// draw avatar or default image
if (self_has_avatar()) {
drawavatarimage(self.avatar.image, SELF_AVATAR_X, SELF_AVATAR_Y, self.avatar.width, self.avatar.height, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH);
draw_avatar_image(self.avatar.image, SELF_AVATAR_X, SELF_AVATAR_Y, self.avatar.width, self.avatar.height, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH);
} else {
drawalpha(BM_CONTACT, SELF_AVATAR_X, SELF_AVATAR_Y, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH, WHITE);
}
Expand All @@ -76,7 +94,7 @@ static void drawfriend(int UNUSED(x), int UNUSED(y), int UNUSED(w), int UNUSED(h

// draw avatar or default image
if (friend_has_avatar(f)) {
drawavatarimage(f->avatar.image, LIST_RIGHT + SCALE * 5, SCALE * 5, f->avatar.width, f->avatar.height, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH);
draw_avatar_image(f->avatar.image, LIST_RIGHT + SCALE * 5, SCALE * 5, f->avatar.width, f->avatar.height, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH);
} else {
drawalpha(BM_CONTACT, LIST_RIGHT + SCALE * 5, SCALE * 5, BM_CONTACT_WIDTH, BM_CONTACT_WIDTH, LIST_MAIN);
}
Expand Down
10 changes: 10 additions & 0 deletions ui.h
Original file line number Diff line number Diff line change
@@ -1,3 +1,13 @@

/* draws an image in the style of an avatar at within rect (x,y,targetwidth,targetheight)
* this means: resize the image while keeping proportion so that the dimension(width or height) that has the smallest rational difference to the targetdimension becomes exactly targetdimension, then
* crop the image so it fits in the (x,y,targetwidth,targetheight) rect, and
* set the position if a dimension is too large so it's centered on the middle
*
* first argument is the image to draw, width and height are the width and height of the input image
*/
void draw_avatar_image(UTOX_NATIVE_IMAGE *image, int x, int y, uint32_t width, uint32_t height, uint32_t targetwidth, uint32_t targetheight);

enum
{
PANEL_NONE,
Expand Down
Loading

0 comments on commit 15961b1

Please sign in to comment.