2 * Copyright (C) 2007-2010 Openismus GmbH
5 * Mathias Hasselmann <mathias@openismus.com>
6 * Tristan Van Berkom <tristan.van.berkom@gmail.com>
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
18 * You should have received a copy of the GNU Library General Public
19 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
24 #include "gtksizerequestcacheprivate.h"
29 _gtk_size_request_cache_init (SizeRequestCache *cache)
31 memset (cache, 0, sizeof (SizeRequestCache));
35 free_sizes (SizeRequest **sizes)
39 for (i = 0; i < GTK_SIZE_REQUEST_CACHED_SIZES && sizes[i] != NULL; i++)
40 g_slice_free (SizeRequest, sizes[i]);
42 g_slice_free1 (sizeof (SizeRequest *) * GTK_SIZE_REQUEST_CACHED_SIZES, sizes);
46 _gtk_size_request_cache_free (SizeRequestCache *cache)
49 free_sizes (cache->widths);
51 free_sizes (cache->heights);
55 _gtk_size_request_cache_clear (SizeRequestCache *cache)
58 _gtk_size_request_cache_free (cache);
59 _gtk_size_request_cache_init (cache);
63 _gtk_size_request_cache_commit (SizeRequestCache *cache,
64 GtkOrientation orientation,
69 SizeRequest **cached_sizes;
72 /* First handle caching of the base requests */
75 if (orientation == GTK_ORIENTATION_HORIZONTAL)
77 cache->cached_width.minimum_size = minimum_size;
78 cache->cached_width.natural_size = natural_size;
79 cache->cached_base_width = TRUE;
83 cache->cached_height.minimum_size = minimum_size;
84 cache->cached_height.natural_size = natural_size;
85 cache->cached_base_height = TRUE;
90 /* Check if the minimum_size and natural_size is already
91 * in the cache and if this result can be used to extend
94 if (orientation == GTK_ORIENTATION_HORIZONTAL)
96 cached_sizes = cache->widths;
97 n_sizes = cache->cached_widths;
101 cached_sizes = cache->heights;
102 n_sizes = cache->cached_heights;
105 for (i = 0; i < n_sizes; i++)
107 if (cached_sizes[i]->cached_size.minimum_size == minimum_size &&
108 cached_sizes[i]->cached_size.natural_size == natural_size)
110 cached_sizes[i]->lower_for_size = MIN (cached_sizes[i]->lower_for_size, for_size);
111 cached_sizes[i]->upper_for_size = MAX (cached_sizes[i]->upper_for_size, for_size);
116 /* If not found, pull a new size from the cache, the returned size cache
117 * will immediately be used to cache the new computed size so we go ahead
118 * and increment the last_cached_width/height right away */
119 if (orientation == GTK_ORIENTATION_HORIZONTAL)
121 if (cache->cached_widths < GTK_SIZE_REQUEST_CACHED_SIZES)
123 cache->cached_widths++;
124 cache->last_cached_width = cache->cached_widths - 1;
128 if (++cache->last_cached_width == GTK_SIZE_REQUEST_CACHED_SIZES)
129 cache->last_cached_width = 0;
133 cache->widths = g_slice_alloc0 (sizeof (SizeRequest *) * GTK_SIZE_REQUEST_CACHED_SIZES);
135 if (!cache->widths[cache->last_cached_width])
136 cache->widths[cache->last_cached_width] = g_slice_new (SizeRequest);
138 cache->widths[cache->last_cached_width]->lower_for_size = for_size;
139 cache->widths[cache->last_cached_width]->upper_for_size = for_size;
140 cache->widths[cache->last_cached_width]->cached_size.minimum_size = minimum_size;
141 cache->widths[cache->last_cached_width]->cached_size.natural_size = natural_size;
143 else /* GTK_ORIENTATION_VERTICAL */
145 if (cache->cached_heights < GTK_SIZE_REQUEST_CACHED_SIZES)
147 cache->cached_heights++;
148 cache->last_cached_height = cache->cached_heights - 1;
152 if (++cache->last_cached_height == GTK_SIZE_REQUEST_CACHED_SIZES)
153 cache->last_cached_height = 0;
157 cache->heights = g_slice_alloc0 (sizeof (SizeRequest *) * GTK_SIZE_REQUEST_CACHED_SIZES);
159 if (!cache->heights[cache->last_cached_height])
160 cache->heights[cache->last_cached_height] = g_slice_new (SizeRequest);
162 cache->heights[cache->last_cached_height]->lower_for_size = for_size;
163 cache->heights[cache->last_cached_height]->upper_for_size = for_size;
164 cache->heights[cache->last_cached_height]->cached_size.minimum_size = minimum_size;
165 cache->heights[cache->last_cached_height]->cached_size.natural_size = natural_size;
169 /* looks for a cached size request for this for_size.
171 * Note that this caching code was originally derived from
172 * the Clutter toolkit but has evolved for other GTK+ requirements.
175 _gtk_size_request_cache_lookup (SizeRequestCache *cache,
176 GtkOrientation orientation,
181 CachedSize *result = NULL;
185 if (orientation == GTK_ORIENTATION_HORIZONTAL)
187 if (cache->cached_base_width)
188 result = &cache->cached_width;
192 if (cache->cached_base_height)
193 result = &cache->cached_height;
198 SizeRequest **cached_sizes;
201 if (orientation == GTK_ORIENTATION_HORIZONTAL)
203 cached_sizes = cache->widths;
204 n_sizes = cache->cached_widths;
208 cached_sizes = cache->heights;
209 n_sizes = cache->cached_heights;
212 /* Search for an already cached size */
213 for (i = 0; i < n_sizes; i++)
215 if (cached_sizes[i]->lower_for_size <= for_size &&
216 cached_sizes[i]->upper_for_size >= for_size)
218 result = &cached_sizes[i]->cached_size;
226 *minimum = result->minimum_size;
227 *natural = result->natural_size;