blob: c4ed04e4757c1581d9244a1d223aadd664b7da21 [file] [log] [blame]
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +00001/* Copyright (C) 2000-2005 Constantin Kaplinsky. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18
19//
20// TightPalette class implementation.
21//
22
23#include <rfb/TightPalette.h>
24
25using namespace rfb;
26
27TightPalette::TightPalette(int maxColors)
28{
29 setMaxColors(maxColors);
30 reset();
31}
32
33void TightPalette::reset()
34{
35 m_numColors = 0;
36 memset(m_hash, 0, 256 * sizeof(TightColorList *));
37}
38
39void TightPalette::setMaxColors(int maxColors)
40{
41 m_maxColors = maxColors;
42 if (m_maxColors < 0) {
43 m_maxColors = 0;
44 } else if (m_maxColors > 254) {
45 m_maxColors = 254;
46 }
47}
48
49int TightPalette::insert(rdr::U32 rgb, int numPixels)
50{
51 TightColorList *pnode;
52 TightColorList *prev_pnode = NULL;
53 int hash_key, idx, new_idx, count;
54
55 hash_key = hashFunc(rgb);
56
57 pnode = m_hash[hash_key];
58
59 while (pnode != NULL) {
60 if (pnode->rgb == rgb) {
61 // Such palette entry already exists.
62 new_idx = idx = pnode->idx;
63 count = m_entry[idx].numPixels + numPixels;
64 if (new_idx && m_entry[new_idx-1].numPixels < count) {
65 do {
66 m_entry[new_idx] = m_entry[new_idx-1];
67 m_entry[new_idx].listNode->idx = new_idx;
68 new_idx--;
69 }
70 while (new_idx && m_entry[new_idx-1].numPixels < count);
71
72 m_entry[new_idx].listNode = pnode;
73 pnode->idx = new_idx;
74 }
75 m_entry[new_idx].numPixels = count;
76 return m_numColors;
77 }
78 prev_pnode = pnode;
79 pnode = pnode->next;
80 }
81
82 // Check if the palette is full.
83 if (m_numColors == 256 || m_numColors == m_maxColors) {
84 m_numColors = 0;
85 return 0;
86 }
87
88 // Move palette entries with lesser pixel counts.
89 for ( idx = m_numColors;
90 idx > 0 && m_entry[idx-1].numPixels < numPixels;
91 idx-- ) {
92 m_entry[idx] = m_entry[idx-1];
93 m_entry[idx].listNode->idx = idx;
94 }
95
96 // Add new palette entry into the freed slot.
97 pnode = &m_list[m_numColors];
98 if (prev_pnode != NULL) {
99 prev_pnode->next = pnode;
100 } else {
101 m_hash[hash_key] = pnode;
102 }
103 pnode->next = NULL;
104 pnode->idx = idx;
105 pnode->rgb = rgb;
106 m_entry[idx].listNode = pnode;
107 m_entry[idx].numPixels = numPixels;
108
109 return ++m_numColors;
110}