Evince
Evince is a document viewer capable of displaying multiple and single page document formats like PDF and Postscript.
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
color.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2000, Matias Atria
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  */
18 
19 #include <config.h>
20 #include "mdvi.h"
21 #include "color.h"
22 
24 {
25  if(dvi->curr_fg != fg || dvi->curr_bg != bg) {
26  DEBUG((DBG_DEVICE, "setting color to (%lu,%lu)\n", fg, bg));
27  if(dvi->device.set_color)
28  dvi->device.set_color(dvi->device.device_data, fg, bg);
29  dvi->curr_fg = fg;
30  dvi->curr_bg = bg;
31  }
32 }
33 
35 {
36  if(dvi->color_top == dvi->color_size) {
37  dvi->color_size += 32;
39  dvi->color_size * sizeof(DviColorPair));
40  }
41  dvi->color_stack[dvi->color_top].fg = dvi->curr_fg;
42  dvi->color_stack[dvi->color_top].bg = dvi->curr_bg;
43  dvi->color_top++;
44  mdvi_set_color(dvi, fg, bg);
45 }
46 
48 {
49  Ulong fg, bg;
50 
51  if(dvi->color_top == 0)
52  return;
53  dvi->color_top--;
54  fg = dvi->color_stack[dvi->color_top].fg;
55  bg = dvi->color_stack[dvi->color_top].bg;
56  mdvi_set_color(dvi, fg, bg);
57 }
58 
60 {
61  dvi->color_top = 0;
62  mdvi_set_color(dvi, dvi->params.fg, dvi->params.bg);
63 }
64 
65 /* cache for color tables, to avoid creating them for every glyph */
66 typedef struct {
71  int density;
72  double gamma;
74 } ColorCache;
75 
76 #define CCSIZE 256
78 static int cc_entries;
79 
80 #define GAMMA_DIFF 0.005
81 
82 
83 /* create a color table */
85  int nlevels, Ulong fg, Ulong bg, double gamma, int density)
86 {
87  ColorCache *cc, *tofree;
88  int lohits;
89  Ulong *pixels;
90  int status;
91 
92  lohits = color_cache[0].hits;
93  tofree = &color_cache[0];
94  /* look in the cache and see if we have one that matches this request */
95  for(cc = &color_cache[0]; cc < &color_cache[cc_entries]; cc++) {
96  if(cc->hits < lohits) {
97  lohits = cc->hits;
98  tofree = cc;
99  }
100  if(cc->fg == fg && cc->bg == bg && cc->density == density &&
101  cc->nlevels == nlevels && fabs(cc->gamma - gamma) <= GAMMA_DIFF)
102  break;
103  }
104 
105  if(cc < &color_cache[cc_entries]) {
106  cc->hits++;
107  return cc->pixels;
108  }
109 
110  DEBUG((DBG_DEVICE, "Adding color table to cache (fg=%lu, bg=%lu, n=%d)\n",
111  fg, bg, nlevels));
112 
113  /* no entry was found in the cache, create a new one */
114  if(cc_entries < CCSIZE) {
115  cc = &color_cache[cc_entries++];
116  cc->pixels = NULL;
117  } else {
118  cc = tofree;
119  mdvi_free(cc->pixels);
120  }
121  pixels = xnalloc(Ulong, nlevels);
122  status = dev->alloc_colors(dev->device_data,
123  pixels, nlevels, fg, bg, gamma, density);
124  if(status < 0) {
125  mdvi_free(pixels);
126  return NULL;
127  }
128  cc->fg = fg;
129  cc->bg = bg;
130  cc->gamma = gamma;
131  cc->density = density;
132  cc->nlevels = nlevels;
133  cc->pixels = pixels;
134  cc->hits = 1;
135  return pixels;
136 }