2009-08-29 12:00:53 +00:00
|
|
|
/**************************************************************************
|
|
|
|
*
|
|
|
|
* Tint2 : common windows function
|
|
|
|
*
|
|
|
|
* Copyright (C) 2007 Pål Staurland (staura@gmail.com)
|
2010-11-02 11:40:50 +00:00
|
|
|
* Modified (C) 2008 thierry lorthiois (lorthiois@bbsoft.fr) from Omega distribution
|
2009-08-29 12:00:53 +00:00
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License version 2
|
|
|
|
* as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
|
|
**************************************************************************/
|
|
|
|
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
#include <X11/Xatom.h>
|
2010-01-04 16:25:17 +00:00
|
|
|
#include <X11/extensions/Xrender.h>
|
2009-08-29 12:00:53 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2010-06-11 18:47:26 +00:00
|
|
|
#include <unistd.h>
|
2015-03-01 10:33:05 +00:00
|
|
|
#include <glib.h>
|
2009-08-29 12:00:53 +00:00
|
|
|
#include "common.h"
|
2010-01-09 16:43:14 +00:00
|
|
|
#include "../server.h"
|
2009-08-29 12:00:53 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
2009-10-25 16:36:40 +00:00
|
|
|
void copy_file(const char *pathSrc, const char *pathDest)
|
|
|
|
{
|
|
|
|
FILE *fileSrc, *fileDest;
|
2015-01-20 23:43:51 +00:00
|
|
|
char buffer[100];
|
2009-10-25 16:36:40 +00:00
|
|
|
int nb;
|
|
|
|
|
|
|
|
fileSrc = fopen(pathSrc, "rb");
|
|
|
|
if (fileSrc == NULL) return;
|
|
|
|
|
|
|
|
fileDest = fopen(pathDest, "wb");
|
|
|
|
if (fileDest == NULL) return;
|
|
|
|
|
2015-01-20 23:43:51 +00:00
|
|
|
while ((nb = fread(buffer, 1, sizeof(buffer), fileSrc)) > 0) {
|
|
|
|
if ( nb != fwrite(buffer, 1, nb, fileDest)) {
|
2010-01-10 22:16:27 +00:00
|
|
|
printf("Error while copying file %s to %s\n", pathSrc, pathDest);
|
2015-01-20 23:43:51 +00:00
|
|
|
}
|
|
|
|
}
|
2009-10-25 16:36:40 +00:00
|
|
|
|
|
|
|
fclose (fileDest);
|
|
|
|
fclose (fileSrc);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int parse_line (const char *line, char **key, char **value)
|
|
|
|
{
|
|
|
|
char *a, *b;
|
|
|
|
|
|
|
|
/* Skip useless lines */
|
|
|
|
if ((line[0] == '#') || (line[0] == '\n')) return 0;
|
|
|
|
if (!(a = strchr (line, '='))) return 0;
|
|
|
|
|
|
|
|
/* overwrite '=' with '\0' */
|
|
|
|
a[0] = '\0';
|
|
|
|
*key = strdup (line);
|
|
|
|
a++;
|
|
|
|
|
|
|
|
/* overwrite '\n' with '\0' if '\n' present */
|
|
|
|
if ((b = strchr (a, '\n'))) b[0] = '\0';
|
|
|
|
|
|
|
|
*value = strdup (a);
|
|
|
|
|
|
|
|
g_strstrip(*key);
|
|
|
|
g_strstrip(*value);
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2010-06-11 18:47:26 +00:00
|
|
|
void tint_exec(const char *command)
|
|
|
|
{
|
|
|
|
if (command) {
|
|
|
|
pid_t pid;
|
|
|
|
pid = fork();
|
|
|
|
if (pid == 0) {
|
|
|
|
// change for the fork the signal mask
|
|
|
|
// sigset_t sigset;
|
|
|
|
// sigprocmask(SIG_SETMASK, &sigset, 0);
|
|
|
|
// sigprocmask(SIG_UNBLOCK, &sigset, 0);
|
|
|
|
execl("/bin/sh", "/bin/sh", "-c", command, NULL);
|
|
|
|
_exit(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-01 10:33:05 +00:00
|
|
|
char *expand_tilde(char *s)
|
|
|
|
{
|
|
|
|
const gchar *home = g_get_home_dir();
|
|
|
|
if (home &&
|
|
|
|
(strcmp(s, "~") == 0 ||
|
|
|
|
strstr(s, "~/") == s)) {
|
|
|
|
char *result = calloc(strlen(home) + strlen(s), 1);
|
|
|
|
strcat(result, home);
|
|
|
|
strcat(result, s + 1);
|
|
|
|
return result;
|
|
|
|
} else {
|
|
|
|
return strdup(s);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
char *contract_tilde(char *s)
|
|
|
|
{
|
|
|
|
const gchar *home = g_get_home_dir();
|
|
|
|
if (!home)
|
|
|
|
return strdup(s);
|
|
|
|
|
|
|
|
char *home_slash = calloc(strlen(home) + 1, 1);
|
|
|
|
strcat(home_slash, home);
|
|
|
|
strcat(home_slash, "/");
|
|
|
|
|
|
|
|
if ((strcmp(s, home) == 0 ||
|
|
|
|
strstr(s, home_slash) == s)) {
|
|
|
|
char *result = calloc(strlen(s) - strlen(home) + 1, 1);
|
|
|
|
strcat(result, "~");
|
|
|
|
strcat(result, s + strlen(home));
|
|
|
|
free(home_slash);
|
|
|
|
return result;
|
|
|
|
} else {
|
|
|
|
free(home_slash);
|
|
|
|
return strdup(s);
|
|
|
|
}
|
|
|
|
}
|
2010-06-11 18:47:26 +00:00
|
|
|
|
2009-10-25 16:36:40 +00:00
|
|
|
int hex_char_to_int (char c)
|
|
|
|
{
|
|
|
|
int r;
|
|
|
|
|
|
|
|
if (c >= '0' && c <= '9') r = c - '0';
|
|
|
|
else if (c >= 'a' && c <= 'f') r = c - 'a' + 10;
|
|
|
|
else if (c >= 'A' && c <= 'F') r = c - 'A' + 10;
|
|
|
|
else r = 0;
|
|
|
|
|
|
|
|
return r;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int hex_to_rgb (char *hex, int *r, int *g, int *b)
|
|
|
|
{
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if (hex == NULL || hex[0] != '#') return (0);
|
|
|
|
|
|
|
|
len = strlen (hex);
|
|
|
|
if (len == 3 + 1) {
|
|
|
|
*r = hex_char_to_int (hex[1]);
|
|
|
|
*g = hex_char_to_int (hex[2]);
|
|
|
|
*b = hex_char_to_int (hex[3]);
|
|
|
|
}
|
|
|
|
else if (len == 6 + 1) {
|
|
|
|
*r = hex_char_to_int (hex[1]) * 16 + hex_char_to_int (hex[2]);
|
|
|
|
*g = hex_char_to_int (hex[3]) * 16 + hex_char_to_int (hex[4]);
|
|
|
|
*b = hex_char_to_int (hex[5]) * 16 + hex_char_to_int (hex[6]);
|
|
|
|
}
|
|
|
|
else if (len == 12 + 1) {
|
|
|
|
*r = hex_char_to_int (hex[1]) * 16 + hex_char_to_int (hex[2]);
|
|
|
|
*g = hex_char_to_int (hex[5]) * 16 + hex_char_to_int (hex[6]);
|
|
|
|
*b = hex_char_to_int (hex[9]) * 16 + hex_char_to_int (hex[10]);
|
|
|
|
}
|
|
|
|
else return 0;
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void get_color (char *hex, double *rgb)
|
|
|
|
{
|
|
|
|
int r, g, b;
|
2015-01-20 23:45:25 +00:00
|
|
|
r = g = b = 0;
|
2009-10-25 16:36:40 +00:00
|
|
|
hex_to_rgb (hex, &r, &g, &b);
|
|
|
|
|
|
|
|
rgb[0] = (r / 255.0);
|
|
|
|
rgb[1] = (g / 255.0);
|
|
|
|
rgb[2] = (b / 255.0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-06-06 09:16:51 +00:00
|
|
|
void extract_values (const char *value, char **value1, char **value2, char **value3)
|
|
|
|
{
|
|
|
|
char *b=0, *c=0;
|
|
|
|
|
|
|
|
if (*value1) free (*value1);
|
|
|
|
if (*value2) free (*value2);
|
|
|
|
if (*value3) free (*value3);
|
|
|
|
|
|
|
|
if ((b = strchr (value, ' '))) {
|
|
|
|
b[0] = '\0';
|
|
|
|
b++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
*value2 = 0;
|
|
|
|
*value3 = 0;
|
|
|
|
}
|
|
|
|
*value1 = strdup (value);
|
|
|
|
g_strstrip(*value1);
|
|
|
|
|
|
|
|
if (b) {
|
|
|
|
if ((c = strchr (b, ' '))) {
|
|
|
|
c[0] = '\0';
|
|
|
|
c++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
c = 0;
|
|
|
|
*value3 = 0;
|
|
|
|
}
|
|
|
|
*value2 = strdup (b);
|
|
|
|
g_strstrip(*value2);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (c) {
|
|
|
|
*value3 = strdup (c);
|
|
|
|
g_strstrip(*value3);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2009-09-19 20:56:15 +00:00
|
|
|
void adjust_asb(DATA32 *data, int w, int h, int alpha, float satur, float bright)
|
2009-08-29 12:00:53 +00:00
|
|
|
{
|
2009-09-01 15:56:52 +00:00
|
|
|
unsigned int x, y;
|
2009-08-29 12:00:53 +00:00
|
|
|
unsigned int a, r, g, b, argb;
|
2009-09-01 15:56:52 +00:00
|
|
|
unsigned long id;
|
2009-08-29 12:00:53 +00:00
|
|
|
int cmax, cmin;
|
|
|
|
float h2, f, p, q, t;
|
|
|
|
float hue, saturation, brightness;
|
|
|
|
float redc, greenc, bluec;
|
|
|
|
|
|
|
|
for(y = 0; y < h; y++) {
|
2009-09-01 15:56:52 +00:00
|
|
|
for(id = y * w, x = 0; x < w; x++, id++) {
|
|
|
|
argb = data[id];
|
2009-08-29 12:00:53 +00:00
|
|
|
a = (argb >> 24) & 0xff;
|
2009-09-19 20:56:15 +00:00
|
|
|
// transparent => nothing to do.
|
|
|
|
if (a == 0) continue;
|
2009-08-29 12:00:53 +00:00
|
|
|
r = (argb >> 16) & 0xff;
|
|
|
|
g = (argb >> 8) & 0xff;
|
|
|
|
b = (argb) & 0xff;
|
|
|
|
|
|
|
|
// convert RGB to HSB
|
|
|
|
cmax = (r > g) ? r : g;
|
|
|
|
if (b > cmax) cmax = b;
|
|
|
|
cmin = (r < g) ? r : g;
|
|
|
|
if (b < cmin) cmin = b;
|
|
|
|
brightness = ((float)cmax) / 255.0f;
|
|
|
|
if (cmax != 0)
|
|
|
|
saturation = ((float)(cmax - cmin)) / ((float)cmax);
|
|
|
|
else
|
|
|
|
saturation = 0;
|
|
|
|
if (saturation == 0)
|
|
|
|
hue = 0;
|
|
|
|
else {
|
|
|
|
redc = ((float)(cmax - r)) / ((float)(cmax - cmin));
|
|
|
|
greenc = ((float)(cmax - g)) / ((float)(cmax - cmin));
|
|
|
|
bluec = ((float)(cmax - b)) / ((float)(cmax - cmin));
|
|
|
|
if (r == cmax)
|
|
|
|
hue = bluec - greenc;
|
|
|
|
else if (g == cmax)
|
|
|
|
hue = 2.0f + redc - bluec;
|
|
|
|
else
|
|
|
|
hue = 4.0f + greenc - redc;
|
|
|
|
hue = hue / 6.0f;
|
|
|
|
if (hue < 0)
|
|
|
|
hue = hue + 1.0f;
|
|
|
|
}
|
|
|
|
|
|
|
|
// adjust
|
|
|
|
saturation += satur;
|
|
|
|
if (saturation < 0.0) saturation = 0.0;
|
|
|
|
if (saturation > 1.0) saturation = 1.0;
|
|
|
|
brightness += bright;
|
|
|
|
if (brightness < 0.0) brightness = 0.0;
|
|
|
|
if (brightness > 1.0) brightness = 1.0;
|
2009-09-19 20:56:15 +00:00
|
|
|
if (alpha != 100)
|
|
|
|
a = (a * alpha)/100;
|
2009-08-29 12:00:53 +00:00
|
|
|
|
|
|
|
// convert HSB to RGB
|
|
|
|
if (saturation == 0) {
|
|
|
|
r = g = b = (int)(brightness * 255.0f + 0.5f);
|
|
|
|
} else {
|
|
|
|
h2 = (hue - (int)hue) * 6.0f;
|
|
|
|
f = h2 - (int)(h2);
|
|
|
|
p = brightness * (1.0f - saturation);
|
|
|
|
q = brightness * (1.0f - saturation * f);
|
|
|
|
t = brightness * (1.0f - (saturation * (1.0f - f)));
|
|
|
|
switch ((int) h2) {
|
|
|
|
case 0:
|
|
|
|
r = (int)(brightness * 255.0f + 0.5f);
|
|
|
|
g = (int)(t * 255.0f + 0.5f);
|
|
|
|
b = (int)(p * 255.0f + 0.5f);
|
|
|
|
break;
|
|
|
|
case 1:
|
|
|
|
r = (int)(q * 255.0f + 0.5f);
|
|
|
|
g = (int)(brightness * 255.0f + 0.5f);
|
|
|
|
b = (int)(p * 255.0f + 0.5f);
|
|
|
|
break;
|
|
|
|
case 2:
|
|
|
|
r = (int)(p * 255.0f + 0.5f);
|
|
|
|
g = (int)(brightness * 255.0f + 0.5f);
|
|
|
|
b = (int)(t * 255.0f + 0.5f);
|
|
|
|
break;
|
|
|
|
case 3:
|
|
|
|
r = (int)(p * 255.0f + 0.5f);
|
|
|
|
g = (int)(q * 255.0f + 0.5f);
|
|
|
|
b = (int)(brightness * 255.0f + 0.5f);
|
|
|
|
break;
|
|
|
|
case 4:
|
|
|
|
r = (int)(t * 255.0f + 0.5f);
|
|
|
|
g = (int)(p * 255.0f + 0.5f);
|
|
|
|
b = (int)(brightness * 255.0f + 0.5f);
|
|
|
|
break;
|
|
|
|
case 5:
|
|
|
|
r = (int)(brightness * 255.0f + 0.5f);
|
|
|
|
g = (int)(p * 255.0f + 0.5f);
|
|
|
|
b = (int)(q * 255.0f + 0.5f);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
argb = a;
|
|
|
|
argb = (argb << 8) + r;
|
|
|
|
argb = (argb << 8) + g;
|
|
|
|
argb = (argb << 8) + b;
|
2009-09-01 15:56:52 +00:00
|
|
|
data[id] = argb;
|
2009-08-29 12:00:53 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-01-03 00:33:07 +00:00
|
|
|
void createHeuristicMask(DATA32* data, int w, int h)
|
|
|
|
{
|
2010-01-18 21:11:05 +00:00
|
|
|
// first we need to find the mask color, therefore we check all 4 edge pixel and take the color which
|
|
|
|
// appears most often (we only need to check three edges, the 4th is implicitly clear)
|
|
|
|
unsigned int topLeft = data[0], topRight = data[w-1], bottomLeft = data[w*h-w], bottomRight = data[w*h-1];
|
|
|
|
int max = (topLeft == topRight) + (topLeft == bottomLeft) + (topLeft == bottomRight);
|
|
|
|
int maskPos = 0;
|
|
|
|
if ( max < (topRight == topLeft) + (topRight == bottomLeft) + (topRight == bottomRight) ) {
|
|
|
|
max = (topRight == topLeft) + (topRight == bottomLeft) + (topRight == bottomRight);
|
|
|
|
maskPos = w-1;
|
|
|
|
}
|
|
|
|
if ( max < (bottomLeft == topRight) + (bottomLeft == topLeft) + (bottomLeft == bottomRight) )
|
|
|
|
maskPos = w*h-w;
|
|
|
|
|
|
|
|
// now mask out every pixel which has the same color as the edge pixels
|
2010-01-03 00:33:07 +00:00
|
|
|
unsigned char* udata = (unsigned char*)data;
|
2010-01-18 21:11:05 +00:00
|
|
|
unsigned char b = udata[4*maskPos];
|
|
|
|
unsigned char g = udata[4*maskPos+1];
|
|
|
|
unsigned char r = udata[4*maskPos+1];
|
2010-01-03 00:33:07 +00:00
|
|
|
int i;
|
|
|
|
for (i=0; i<h*w; ++i) {
|
2010-01-18 21:11:05 +00:00
|
|
|
if ( b-udata[0] == 0 && g-udata[1] == 0 && r-udata[2] == 0 )
|
|
|
|
udata[3] = 0;
|
2010-01-03 00:33:07 +00:00
|
|
|
udata += 4;
|
|
|
|
}
|
|
|
|
}
|
2010-01-04 16:25:17 +00:00
|
|
|
|
|
|
|
|
|
|
|
void render_image(Drawable d, int x, int y, int w, int h)
|
|
|
|
{
|
|
|
|
// in real_transparency mode imlib_render_image_on_drawable does not the right thing, because
|
|
|
|
// the operation is IMLIB_OP_COPY, but we would need IMLIB_OP_OVER (which does not exist)
|
|
|
|
// Therefore we have to do it with the XRender extension (i.e. copy what imlib is doing internally)
|
|
|
|
// But first we need to render the image onto itself with PictOpIn to adjust the colors to the alpha channel
|
|
|
|
Pixmap pmap_tmp = XCreatePixmap(server.dsp, server.root_win, w, h, 32);
|
|
|
|
imlib_context_set_drawable(pmap_tmp);
|
|
|
|
imlib_context_set_blend(0);
|
|
|
|
imlib_render_image_on_drawable(0, 0);
|
|
|
|
Picture pict_image = XRenderCreatePicture(server.dsp, pmap_tmp, XRenderFindStandardFormat(server.dsp, PictStandardARGB32), 0, 0);
|
|
|
|
Picture pict_drawable = XRenderCreatePicture(server.dsp, d, XRenderFindVisualFormat(server.dsp, server.visual), 0, 0);
|
|
|
|
XRenderComposite(server.dsp, PictOpIn, pict_image, None, pict_image, 0, 0, 0, 0, 0, 0, w, h);
|
|
|
|
XRenderComposite(server.dsp, PictOpOver, pict_image, None, pict_drawable, 0, 0, 0, 0, x, y, w, h);
|
2010-02-28 07:58:50 +00:00
|
|
|
imlib_context_set_blend(1);
|
2010-01-04 16:25:17 +00:00
|
|
|
XFreePixmap(server.dsp, pmap_tmp);
|
|
|
|
XRenderFreePicture(server.dsp, pict_image);
|
|
|
|
XRenderFreePicture(server.dsp, pict_drawable);
|
|
|
|
}
|