1 /* aicon.cc
2 * This file belongs to Worker, a file manager for UN*X/X11.
3 * Copyright (C) 2019 Ralf Hoffmann.
4 * You can contact me at: ralf@boomerangsworld.de
5 * or http://www.boomerangsworld.de/worker
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 #include "aguix.h"
23 #include "aicon.hh"
24 #include <iostream>
25
AIcon(AGUIX * aguix,Drawable d,const int * pixels,size_t pixels_length)26 AIcon::AIcon( AGUIX *aguix,
27 Drawable d,
28 const int *pixels,
29 size_t pixels_length ) :
30 m_aguix( aguix ),
31 m_d( d ),
32 m_w( 0 ),
33 m_h( 0 ),
34 m_scale_factor( 0 ),
35 m_aguix_color_instance( -1 ),
36 m_current_fg( -1 ),
37 m_current_bg( -1 )
38 {
39 if ( pixels_length < 3 ) {
40 std::cerr << "Invalid pixels field" << std::endl;
41 return;
42 }
43
44 size_t w = pixels[0];
45 size_t h = pixels[1];
46
47 if ( w * h + 2 != pixels_length ) {
48 std::cerr << "Invalid pixels field" << std::endl;
49 return;
50 }
51
52 m_w = w;
53 m_h = h;
54
55 for ( size_t p = 0; p < w * h; p++ ) {
56 m_pixels.push_back( pixels[ 2 + p ] );
57 }
58
59 update( 1, 0, true );
60 }
61
~AIcon()62 AIcon::~AIcon()
63 {
64 cleanPixmapCache();
65 }
66
update(Drawable d,int fg,int bg,bool force)67 void AIcon::update( Drawable d, int fg, int bg, bool force )
68 {
69 if ( m_d != d ) {
70 m_d = d;
71 force = true;
72 }
73
74 update( fg, bg, force );
75 }
76
update(int fg,int bg,bool force)77 void AIcon::update( int fg, int bg, bool force )
78 {
79 if ( m_d == 0 ) return;
80
81 if ( m_w < 1 || m_h < 1 ) return;
82
83 if ( ! force &&
84 m_current_fg == fg &&
85 m_current_bg == bg &&
86 m_aguix_color_instance == m_aguix->getCurrentUserColorInstance() ) {
87 return;
88 }
89
90 auto id = std::make_pair( fg, bg );
91
92 if ( m_aguix_color_instance != m_aguix->getCurrentUserColorInstance() ) {
93 // remove cache
94 cleanPixmapCache();
95 }
96
97 bool skip_update = false;
98
99 if ( m_pixmap_cache.count( id ) > 0 ) {
100 if ( ! force ) {
101 skip_update = true;
102 } else {
103 m_aguix->freePixmap( m_pixmap_cache[id] );
104 m_pixmap_cache.erase( id );
105 }
106 }
107
108 if ( ! skip_update ) {
109 size_t factor = 1;
110 if ( m_scale_factor > 1 ) {
111 factor = m_scale_factor;
112 }
113
114 Pixmap pixmap = m_aguix->createPixmap( m_d, m_w * factor, m_h * factor );
115
116 if ( pixmap != 0 ) {
117 AGUIX::col_values_t fg_values = m_aguix->getColorInfo( fg );
118 AGUIX::col_values_t bg_values = m_aguix->getColorInfo( bg );
119
120 for ( size_t y = 0; y < m_h * factor; y++ ) {
121 for ( size_t x = 0; x < m_w * factor; x++ ) {
122 int c = m_pixels.at( ( y / factor ) * m_w + x / factor );
123
124 AGUIX::col_values_t color = m_aguix->blend( bg_values,
125 fg_values,
126 c );
127
128 AGUIXColor acol = m_aguix->getColor( color );
129
130 m_aguix->setFG( acol );
131
132 m_aguix->DrawPoint( pixmap, x, y );
133 }
134 }
135
136 m_pixmap_cache[id] = pixmap;
137 }
138 }
139
140 m_current_fg = fg;
141 m_current_bg = bg;
142 m_aguix_color_instance = m_aguix->getCurrentUserColorInstance();
143 }
144
draw(Drawable d,int x,int y)145 void AIcon::draw( Drawable d,
146 int x, int y )
147 {
148 try {
149 Pixmap pixmap = m_pixmap_cache.at( std::make_pair( m_current_fg,
150 m_current_bg ) );
151
152 size_t factor = 1;
153 if ( m_scale_factor > 1 ) {
154 factor = m_scale_factor;
155 }
156
157 m_aguix->copyArea( pixmap,
158 d,
159 0, 0,
160 m_w * factor, m_h * factor,
161 x, y );
162 } catch (...) {
163 }
164 }
165
w() const166 size_t AIcon::w() const
167 {
168 return m_w;
169 }
170
h() const171 size_t AIcon::h() const
172 {
173 return m_h;
174 }
175
setScale(size_t factor)176 void AIcon::setScale( size_t factor )
177 {
178 m_scale_factor = factor;
179 }
180
drawable() const181 Drawable AIcon::drawable() const
182 {
183 return m_d;
184 }
185
cleanPixmapCache()186 void AIcon::cleanPixmapCache()
187 {
188 for ( auto it : m_pixmap_cache ) {
189 m_aguix->freePixmap( it.second );
190 }
191 m_pixmap_cache.clear();
192 }
193