void HandlePixbufLoaded(PixbufCache Cache, PixbufCache.CacheEntry entry) { Pixbuf result = entry.ShallowCopyPixbuf(); int order = (int)entry.Data; if (result == null) { return; } // We have to do the scaling here rather than on load because we need to preserve the // Pixbuf option iformation to verify the thumbnail validity later int width, height; PixbufUtils.Fit(result, ThumbnailWidth, ThumbnailHeight, false, out width, out height); if (result.Width > width && result.Height > height) { // Log.Debug ("scaling"); Pixbuf temp = result.ScaleSimple(width, height, InterpType.Nearest); result.Dispose(); result = temp; } else if (result.Width < ThumbnailWidth && result.Height < ThumbnailHeight) { // FIXME this is a workaround to handle images whose actual size is smaller than // the thumbnail size, it needs to be fixed at a different level. Pixbuf temp = new Pixbuf(Colorspace.Rgb, true, 8, ThumbnailWidth, ThumbnailHeight); temp.Fill(0x00000000); result.CopyArea(0, 0, result.Width, result.Height, temp, (temp.Width - result.Width) / 2, temp.Height - result.Height); result.Dispose(); result = temp; } Cache.Update(entry, result); InvalidateCell(order); }
// FIXME Cache the GCs? protected virtual void DrawPhoto(int cell_num, Rectangle cell_area, Rectangle expose_area, bool selected, bool focussed) { if (!cell_area.Intersect(expose_area, out expose_area)) { return; } IPhoto photo = Collection [cell_num]; PixbufCache.CacheEntry entry = Cache.Lookup(photo.DefaultVersion.Uri); if (entry == null) { Cache.Request(photo.DefaultVersion.Uri, cell_num, ThumbnailWidth, ThumbnailHeight); } else { entry.Data = cell_num; } StateType cell_state = selected ? (HasFocus ? StateType.Selected : StateType.Active) : State; if (cell_state != State) { Style.PaintBox(Style, BinWindow, cell_state, ShadowType.Out, expose_area, this, "IconView", cell_area.X, cell_area.Y, cell_area.Width - 1, cell_area.Height - 1); } var focus = Rectangle.Inflate(cell_area, -3, -3); if (HasFocus && focussed) { Style.PaintFocus(Style, BinWindow, cell_state, expose_area, this, null, focus.X, focus.Y, focus.Width, focus.Height); } var region = Rectangle.Zero; var image_bounds = Rectangle.Inflate(cell_area, -CELL_BORDER_WIDTH, -CELL_BORDER_WIDTH); int expansion = ThrobExpansion(cell_num, selected); Pixbuf thumbnail = null; if (entry != null) { thumbnail = entry.ShallowCopyPixbuf(); } var draw = Rectangle.Zero; if (Rectangle.Inflate(image_bounds, expansion + 1, expansion + 1).Intersect(expose_area, out image_bounds) && thumbnail != null) { PixbufUtils.Fit(thumbnail, ThumbnailWidth, ThumbnailHeight, true, out region.Width, out region.Height); region.X = (int)(cell_area.X + (cell_area.Width - region.Width) / 2); region.Y = (int)cell_area.Y + ThumbnailHeight - region.Height + CELL_BORDER_WIDTH; if (Math.Abs(region.Width - thumbnail.Width) > 1 && Math.Abs(region.Height - thumbnail.Height) > 1) { Cache.Reload(entry, cell_num, thumbnail.Width, thumbnail.Height); } region = Rectangle.Inflate(region, expansion, expansion); Pixbuf temp_thumbnail; region.Width = Math.Max(1, region.Width); region.Height = Math.Max(1, region.Height); if (Math.Abs(region.Width - thumbnail.Width) > 1 && Math.Abs(region.Height - thumbnail.Height) > 1) { if (region.Width < thumbnail.Width && region.Height < thumbnail.Height) { /* * temp_thumbnail = PixbufUtils.ScaleDown (thumbnail, * region.Width, region.Height); */ temp_thumbnail = thumbnail.ScaleSimple(region.Width, region.Height, InterpType.Bilinear); lock (entry) { if (entry.Reload && expansion == 0 && !entry.IsDisposed) { entry.SetPixbufExtended(temp_thumbnail.ShallowCopy(), false); entry.Reload = true; } } } else { temp_thumbnail = thumbnail.ScaleSimple(region.Width, region.Height, InterpType.Bilinear); } } else { temp_thumbnail = thumbnail; } // FIXME There seems to be a rounding issue between the // scaled thumbnail sizes, we avoid this for now by using // the actual thumnail sizes here. region.Width = temp_thumbnail.Width; region.Height = temp_thumbnail.Height; draw = Rectangle.Inflate(region, 1, 1); if (!temp_thumbnail.HasAlpha) { Style.PaintShadow(Style, BinWindow, cell_state, ShadowType.Out, expose_area, this, "IconView", draw.X, draw.Y, draw.Width, draw.Height); } if (region.Intersect(expose_area, out draw)) { Cms.Profile screen_profile; if (ColorManagement.Profiles.TryGetValue(Preferences.Get <string> (Preferences.COLOR_MANAGEMENT_DISPLAY_PROFILE), out screen_profile)) { Pixbuf t = temp_thumbnail.Copy(); temp_thumbnail.Dispose(); temp_thumbnail = t; ColorManagement.ApplyProfile(temp_thumbnail, screen_profile); } temp_thumbnail.RenderToDrawable(BinWindow, Style.WhiteGC, draw.X - region.X, draw.Y - region.Y, draw.X, draw.Y, draw.Width, draw.Height, RgbDither.None, draw.X, draw.Y); } if (temp_thumbnail != thumbnail) { temp_thumbnail.Dispose(); } } if (thumbnail != null) { thumbnail.Dispose(); } // Render Decorations if (DisplayRatings && region.X == draw.X && region.X != 0) { rating_renderer.Render(BinWindow, this, region, expose_area, cell_state, photo); } // Render Captions Rectangle caption_area = Rectangle.Zero; caption_area.Y = cell_area.Y + CELL_BORDER_WIDTH + ThumbnailHeight + CAPTION_PADDING; caption_area.X = cell_area.X + CELL_BORDER_WIDTH; caption_area.Width = cell_area.Width - 2 * CELL_BORDER_WIDTH; if (DisplayDates) { caption_area.Height = date_renderer.GetHeight(this, ThumbnailWidth); date_renderer.Render(BinWindow, this, caption_area, expose_area, cell_state, photo); caption_area.Y += caption_area.Height; } if (DisplayFilenames) { caption_area.Height = filename_renderer.GetHeight(this, ThumbnailWidth); filename_renderer.Render(BinWindow, this, caption_area, expose_area, cell_state, photo); caption_area.Y += caption_area.Height; } if (DisplayTags) { caption_area.Height = tag_renderer.GetHeight(this, ThumbnailWidth); tag_renderer.Render(BinWindow, this, caption_area, expose_area, cell_state, photo); caption_area.Y += caption_area.Height; } }