X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=hacks%2Fglx%2Fphotopile.c;h=29617aa05ef4004d7581e0a90719dbae64bab596;hb=d1ae2829ff0fd2a96c16a0c8c5420efaa47d7b30;hp=53fc7c733be2ce5efeedd34e3008f7d0a71dd198;hpb=5f1f12f2a37da634000f96d18d59cc73a8814ef7;p=xscreensaver diff --git a/hacks/glx/photopile.c b/hacks/glx/photopile.c index 53fc7c73..29617aa0 100644 --- a/hacks/glx/photopile.c +++ b/hacks/glx/photopile.c @@ -1,4 +1,4 @@ -/* photopile, Copyright (c) 2008-2009 Jens Kilian +/* photopile, Copyright (c) 2008-2015 Jens Kilian * Based on carousel, Copyright (c) 2005-2008 Jamie Zawinski * Loads a sequence of images and shuffles them into a pile. * @@ -11,7 +11,7 @@ * implied warranty. */ -#define DEF_FONT "-*-helvetica-bold-r-normal-*-240-*" +#define DEF_FONT "-*-helvetica-bold-r-normal-*-*-480-*-*-*-*-*-*" #define DEFAULTS "*count: 7 \n" \ "*delay: 10000 \n" \ "*wireframe: False \n" \ @@ -76,7 +76,7 @@ typedef struct { } image; -typedef enum { EARLY, IN, NORMAL, LOADING, SHUFFLE } fade_mode; +typedef enum { EARLY, SHUFFLE, NORMAL, LOADING } fade_mode; static int fade_ticks = 60; typedef struct { @@ -109,7 +109,8 @@ static int duration; /* Reload images after this long. */ static Bool mipmap_p; /* Use mipmaps instead of single textures. */ static Bool titles_p; /* Display image titles. */ static Bool polaroid_p; /* Use instant-film look for images. */ -static Bool clip_p; /* Clip images instead of scaling for -polaroid. */static Bool shadows_p; /* Draw drop shadows. */ +static Bool clip_p; /* Clip images instead of scaling for -polaroid. */ +static Bool shadows_p; /* Draw drop shadows. */ static Bool debug_p; /* Be loud and do weird things. */ @@ -208,7 +209,9 @@ set_new_positions(photopile_state *ss) for (i = 0; i < MI_COUNT(mi)+1; ++i) { image *frame = ss->frames + i; - GLfloat d = sqrt(frame->w*frame->w + frame->h*frame->h); + GLfloat w = frame->w; + GLfloat h = frame->h; + GLfloat d = sqrt(w*w + h*h); GLfloat leave = frand(M_PI * 2.0); GLfloat enter = frand(M_PI * 2.0); @@ -220,6 +223,10 @@ set_new_positions(photopile_state *ss) frame->pos[3].y = BELLRAND(MI_HEIGHT(mi)); frame->pos[3].angle = (frand(2.0) - 1.0) * max_tilt; + /* Try to keep the images mostly inside the screen bounds */ + frame->pos[3].x = MAX(0.5*w, MIN(MI_WIDTH(mi)-0.5*w, frame->pos[3].x)); + frame->pos[3].y = MAX(0.5*h, MIN(MI_HEIGHT(mi)-0.5*h, frame->pos[3].y)); + /* intermediate points */ frame->pos[1] = offset_pos(frame->pos[0], leave, d * (0.5 + frand(1.0))); frame->pos[2] = offset_pos(frame->pos[3], enter, d * (0.5 + frand(1.0))); @@ -278,8 +285,12 @@ image_loaded_cb (const char *filename, XRectangle *geom, free (frame->title); frame->title = (filename ? strdup (filename) : 0); - if (frame->title) /* strip filename to part after last /. */ + /* xscreensaver-getimage returns paths relative to the image directory + now, so leave the sub-directory part in. Unless it's an absolute path. + */ + if (frame->title && frame->title[0] == '/') { + /* strip filename to part after last /. */ char *s = strrchr (frame->title, '/'); if (s) strcpy (frame->title, s+1); } @@ -342,7 +353,12 @@ loading_msg (ModeInfo *mi) if (wire) return; if (ss->loading_sw == 0) /* only do this once */ - ss->loading_sw = texture_string_width (ss->texfont, text, &ss->loading_sh); + { + XCharStruct e; + texture_string_metrics (ss->texfont, text, &e, 0, 0); + ss->loading_sw = e.width; + ss->loading_sh = e.ascent + e.descent; + } glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -353,7 +369,7 @@ loading_msg (ModeInfo *mi) glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); - gluOrtho2D(0, MI_WIDTH(mi), 0, MI_HEIGHT(mi)); + glOrtho(0, MI_WIDTH(mi), 0, MI_HEIGHT(mi), -1, 1); glTranslatef ((MI_WIDTH(mi) - ss->loading_sw) / 2, (MI_HEIGHT(mi) - ss->loading_sh) / 2, @@ -415,7 +431,7 @@ reshape_photopile (ModeInfo *mi, int width, int height) glMatrixMode(GL_MODELVIEW); glLoadIdentity(); - gluOrtho2D(0, MI_WIDTH(mi), 0, MI_HEIGHT(mi)); + glOrtho(0, MI_WIDTH(mi), 0, MI_HEIGHT(mi), -1, 1); glClear(GL_COLOR_BUFFER_BIT); } @@ -459,23 +475,11 @@ init_photopile (ModeInfo *mi) if ((ss->glx_context = init_GL(mi)) != NULL) { reshape_photopile (mi, MI_WIDTH(mi), MI_HEIGHT(mi)); + clear_gl_error(); /* WTF? sometimes "invalid op" from glViewport! */ } else { MI_CLEARWINDOW(mi); } - glDisable (GL_LIGHTING); - glEnable (GL_DEPTH_TEST); - glDisable (GL_CULL_FACE); - - if (! wire) - { - glShadeModel (GL_SMOOTH); - glEnable (GL_LINE_SMOOTH); - glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); - glEnable (GL_BLEND); - glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - ss->shadow = init_drop_shadow(); ss->texfont = load_texture_font (MI_DISPLAY(mi), "font"); @@ -552,14 +556,23 @@ draw_image (ModeInfo *mi, int i, GLfloat t, GLfloat s, GLfloat z) { glColor3f (0, 0, 0); draw_drop_shadow(ss->shadow, -w1, -h1, z2, 2.0 * w1, h1 + h2, 20.0); + glDisable (GL_BLEND); } + glDisable (GL_LIGHTING); + glEnable (GL_DEPTH_TEST); + glDisable (GL_CULL_FACE); + /* Draw the retro instant-film frame. */ if (polaroid_p) { if (! wire) { + glShadeModel (GL_SMOOTH); + glEnable (GL_LINE_SMOOTH); + glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); + glColor3f (1, 1, 1); glBegin (GL_QUADS); glVertex3f (-w1, -h1, z2); @@ -569,7 +582,7 @@ draw_image (ModeInfo *mi, int i, GLfloat t, GLfloat s, GLfloat z) glEnd(); } - glLineWidth (2.0); + glLineWidth (1.0); glColor3f (0.5, 0.5, 0.5); glBegin (GL_LINE_LOOP); glVertex3f (-w1, -h1, z); @@ -602,7 +615,13 @@ draw_image (ModeInfo *mi, int i, GLfloat t, GLfloat s, GLfloat z) /* Draw a box around it. */ - glLineWidth (2.0); + if (! wire) + { + glShadeModel (GL_SMOOTH); + glEnable (GL_LINE_SMOOTH); + glHint (GL_LINE_SMOOTH_HINT, GL_NICEST); + } + glLineWidth (1.0); glColor3f (0.5, 0.5, 0.5); glBegin (GL_LINE_LOOP); glVertex3f (-w, -h, z); @@ -615,12 +634,26 @@ draw_image (ModeInfo *mi, int i, GLfloat t, GLfloat s, GLfloat z) */ if (titles_p) { - int sw, sh; - GLfloat scale = 0.6; - char *title = frame->title ? frame->title : "(untitled)"; - sw = texture_string_width (ss->texfont, title, &sh); - - glTranslatef (-sw*scale*0.5, -h - sh*scale, z); + int sw, sh, ascent, descent; + GLfloat scale = 1; + const char *title = frame->title ? frame->title : "(untitled)"; + XCharStruct e; + + /* #### Highly approximate, but doing real clipping is harder... */ + int max = 35; + if (strlen(title) > max) + title += strlen(title) - max; + + texture_string_metrics (ss->texfont, title, &e, &ascent, &descent); + sw = e.width; + sh = ascent + descent; + + /* Scale the text to match the pixel size of the photo */ + scale *= w / 300.0; + + /* Move to below photo */ + glTranslatef (0, -h - sh * (polaroid_p ? 2.2 : 0.5), 0); + glTranslatef (-sw*scale/2, sh*scale/2, z); glScalef (scale, scale, 1); if (wire || !polaroid_p) @@ -635,8 +668,8 @@ draw_image (ModeInfo *mi, int i, GLfloat t, GLfloat s, GLfloat z) if (!wire) { glEnable (GL_TEXTURE_2D); + glEnable (GL_BLEND); print_texture_string (ss->texfont, title); - glDisable (GL_TEXTURE_2D); } else { @@ -680,12 +713,19 @@ draw_photopile (ModeInfo *mi) { GLfloat t; + glPushMatrix(); + glTranslatef (MI_WIDTH(mi)/2, MI_HEIGHT(mi)/2, 0); + glRotatef(current_device_rotation(), 0, 0, 1); + glTranslatef (-MI_WIDTH(mi)/2, -MI_HEIGHT(mi)/2, 0); + /* Handle state transitions. */ switch (ss->mode) { - case IN: + case SHUFFLE: if (--ss->mode_tick <= 0) { + ss->nframe = (ss->nframe+1) % (MI_COUNT(mi)+1); + ss->mode = NORMAL; ss->last_time = time((time_t *) 0); } @@ -705,15 +745,6 @@ draw_photopile (ModeInfo *mi) ss->mode_tick = fade_ticks / speed; } break; - case SHUFFLE: - if (--ss->mode_tick <= 0) - { - ss->nframe = (ss->nframe+1) % (MI_COUNT(mi)+1); - - ss->mode = NORMAL; - ss->last_time = time((time_t *) 0); - } - break; default: abort(); } @@ -733,13 +764,6 @@ draw_photopile (ModeInfo *mi) switch (ss->mode) { - case IN: - s *= t; - break; - case NORMAL: - case LOADING: - t = 1.0; - break; case SHUFFLE: if (i == MI_COUNT(mi)) { @@ -750,6 +774,10 @@ draw_photopile (ModeInfo *mi) s *= 1.0 - t; } break; + case NORMAL: + case LOADING: + t = 1.0; + break; default: abort(); } @@ -757,6 +785,7 @@ draw_photopile (ModeInfo *mi) draw_image(mi, j, t, s, z); } } + glPopMatrix(); } if (mi->fps_p) do_fps (mi);