/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ #include "config.h" #include "palette.h" #include #include #include #include #include guac_palette* guac_palette_alloc(cairo_surface_t* surface) { int x, y; int width = cairo_image_surface_get_width(surface); int height = cairo_image_surface_get_height(surface); int stride = cairo_image_surface_get_stride(surface); unsigned char* data = cairo_image_surface_get_data(surface); /* Allocate palette */ guac_palette* palette = (guac_palette*) malloc(sizeof(guac_palette)); memset(palette, 0, sizeof(guac_palette)); for (y=0; y> 12) ^ (color & 0xFFF); guac_palette_entry* entry; /* Search for open palette entry */ for (;;) { entry = &(palette->entries[hash]); /* If we've found a free space, use it */ if (entry->index == 0) { png_color* c; /* Stop if already at capacity */ if (palette->size == 256) { guac_palette_free(palette); return NULL; } /* Store in palette */ c = &(palette->colors[palette->size]); c->blue = (color ) & 0xFF; c->green = (color >> 8 ) & 0xFF; c->red = (color >> 16) & 0xFF; /* Add color to map */ entry->index = ++palette->size; entry->color = color; break; } /* Otherwise, if already stored here, done */ if (entry->color == color) break; /* Otherwise, collision. Move on to another bucket */ hash = (hash+1) & 0xFFF; } } /* Advance to next data row */ data += stride; } return palette; } int guac_palette_find(guac_palette* palette, int color) { /* Calculate hash code */ int hash = ((color & 0xFFF000) >> 12) ^ (color & 0xFFF); guac_palette_entry* entry; /* Search for palette entry */ for (;;) { entry = &(palette->entries[hash]); /* If we've found a free space, color not stored. */ if (entry->index == 0) return -1; /* Otherwise, if color indeed stored here, done */ if (entry->color == color) return entry->index - 1; /* Otherwise, collision. Move on to another bucket */ hash = (hash+1) & 0xFFF; } } void guac_palette_free(guac_palette* palette) { free(palette); }