1 /* ============================================================================
2 * Freetype GL - A C OpenGL Freetype engine
4 * WWW: http://code.google.com/p/freetype-gl/
5 * ----------------------------------------------------------------------------
6 * Copyright 2011,2012 Nicolas P. Rougier. All rights reserved.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions are met:
11 * 1. Redistributions of source code must retain the above copyright notice,
12 * this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY NICOLAS P. ROUGIER ''AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
20 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
21 * EVENT SHALL NICOLAS P. ROUGIER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 * The views and conclusions contained in the software and documentation are
30 * those of the authors and should not be interpreted as representing official
31 * policies, either expressed or implied, of Nicolas P. Rougier.
32 * ============================================================================
37 #include "texture_atlas.h"
39 namespace caspar { namespace core { namespace text {
42 struct texture_atlas::impl
52 typedef std::list<node> node_list;
53 typedef std::list<node>::iterator node_iterator;
60 const unsigned char* dataptr_;
61 std::vector<unsigned char> data_;
65 impl(const size_t width, const size_t height, const size_t depth) : width_(width), height_(height), depth_(depth), data_(width*height*depth, 0)
67 dataptr_ = data_.data();
68 // We want a one pixel border around the whole atlas to avoid any artefact when sampling texture
69 node n = {1, 1, static_cast<int>(width_) - 2};
73 rect get_region(int width, int height)
75 rect region = { 0, 0, static_cast<int>(width), static_cast<int>(height) };
77 int best_height = INT_MAX;
78 int best_width = INT_MAX;
79 node_iterator best_it = nodes_.end();
81 for(auto it = nodes_.begin(); it != nodes_.end(); ++it)
83 int y = fit(it, width, height);
86 if( ( (y + height) < best_height ) ||
87 ( ((y + height) == best_height) && ((*it).width < best_width)) )
89 best_height = y + height;
91 best_width = (*it).width;
98 if(best_it == nodes_.end())
108 new_node.x = region.x;
109 new_node.y = region.y + (int)height;
110 new_node.width = (int)width;
112 best_it = nodes_.insert(best_it, new_node);
114 for(auto it = ++best_it; it != nodes_.end(); ++it)
116 auto prev = it; --prev;
118 if ((*it).x < ((*prev).x + (*prev).width) )
120 int shrink = (*prev).x + (*prev).width - (*it).x;
122 (*it).width -= shrink;
123 if ((*it).width <= 0)
136 used_ += width * height;
140 //the data parameter points to bitmap-data that is 8-bit grayscale.
141 void set_region(const size_t x, const size_t y, const size_t width, const size_t height, const unsigned char *src, const size_t stride, const color<double>& col)
143 //this assumes depth_ is set to 4
144 for(size_t i=0; i<height; ++i)
146 for(size_t j=0; j<width; ++j)
148 unsigned char* pixel = &data_[((y+i)*width_ + x + j)*depth_];
149 unsigned char value = src[i*stride + j];
150 pixel[0] = (unsigned char)(value*col.b);
151 pixel[1] = (unsigned char)(value*col.g);
152 pixel[2] = (unsigned char)(value*col.r);
153 pixel[3] = (unsigned char)(value*col.a);
163 node n = {1,1,(int)width_-2};
165 data_.assign(width_*height_*depth_, 0);
168 size_t depth() { return depth_; }
169 size_t width() { return width_; }
170 size_t height() { return height_; }
171 unsigned char* data() { return data_.data(); }
174 int fit(node_iterator it, const size_t width, const size_t height)
178 int width_left = (int)width;
180 if ((x + width) > (width_ - 1))
183 while( width_left > 0 && it != nodes_.end())
187 if((y + height) > (height_ - 1))
190 width_left -= (*it).width;
199 auto it = nodes_.begin();
202 auto next = it; ++next;
203 if(next == nodes_.end())
206 if((*it).y == (*next).y)
208 (*it).width += (*next).width;
217 texture_atlas::texture_atlas(const size_t w, const size_t h, const size_t d) : impl_(new impl(w, h, d)) {}
218 rect texture_atlas::get_region(int width, int height) { return impl_->get_region(width, height); }
219 void texture_atlas::set_region(const size_t x, const size_t y, const size_t width, const size_t height, const unsigned char *src, const size_t stride, const color<double>& col)
220 { impl_->set_region(x, y, width, height, src, stride, col); }
222 void texture_atlas::clear() { impl_->clear(); }
224 size_t texture_atlas::width() { return impl_->width(); }
225 size_t texture_atlas::height() { return impl_->height(); }
226 size_t texture_atlas::depth() { return impl_->depth(); }
227 unsigned char* texture_atlas::data() { return impl_->data(); }