implement color bitmap extraction/scaling/compositing into target pixmap
This commit is contained in:
parent
639dcae83f
commit
1b67779290
2 changed files with 95 additions and 20 deletions
|
@ -28,6 +28,7 @@
|
|||
#include <mapnik/image_compositing.hpp>
|
||||
#include <mapnik/symbolizer_enumerations.hpp>
|
||||
#include <mapnik/util/noncopyable.hpp>
|
||||
#include <mapnik/pixel_position.hpp>
|
||||
|
||||
#pragma GCC diagnostic push
|
||||
#include <mapnik/warning_ignore.hpp>
|
||||
|
@ -51,8 +52,13 @@ struct glyph_t
|
|||
{
|
||||
FT_Glyph image;
|
||||
detail::evaluated_format_properties const& properties;
|
||||
glyph_t(FT_Glyph image_, detail::evaluated_format_properties const& properties_)
|
||||
: image(image_), properties(properties_) {}
|
||||
pixel_position pos;
|
||||
double size;
|
||||
glyph_t(FT_Glyph image_, detail::evaluated_format_properties const& properties_, pixel_position const& pos_, double size_)
|
||||
: image(image_),
|
||||
properties(properties_),
|
||||
pos(pos_),
|
||||
size(size_) {}
|
||||
};
|
||||
|
||||
class text_renderer : private util::noncopyable
|
||||
|
|
|
@ -25,6 +25,8 @@
|
|||
#include <mapnik/grid/grid.hpp>
|
||||
#include <mapnik/text/text_properties.hpp>
|
||||
#include <mapnik/font_engine_freetype.hpp>
|
||||
#include <mapnik/image_compositing.hpp>
|
||||
#include <mapnik/image_scaling.hpp>
|
||||
#include <mapnik/text/face.hpp>
|
||||
#include <mapnik/image_util.hpp>
|
||||
#include <mapnik/image_any.hpp>
|
||||
|
@ -66,8 +68,35 @@ void text_renderer::prepare_glyphs(glyph_positions const& positions)
|
|||
for (auto const& glyph_pos : positions)
|
||||
{
|
||||
glyph_info const& glyph = glyph_pos.glyph;
|
||||
glyph.face->set_character_sizes(glyph.format->text_size * scale_factor_); //TODO: Optimize this?
|
||||
FT_Int32 load_flags = FT_LOAD_DEFAULT | FT_LOAD_NO_HINTING;
|
||||
|
||||
FT_Face face = glyph.face->get_face();
|
||||
if (glyph.face->is_color())
|
||||
{
|
||||
load_flags |= FT_LOAD_COLOR ;
|
||||
if (face->num_fixed_sizes > 0)
|
||||
{
|
||||
int scaled_size = static_cast<int>(glyph.format->text_size * scale_factor_);
|
||||
int best_match = 0;
|
||||
int diff = std::abs(scaled_size - face->available_sizes[0].width);
|
||||
for (int i = 1; i < face->num_fixed_sizes; ++i)
|
||||
{
|
||||
int ndiff = std::abs(scaled_size - face->available_sizes[i].height);
|
||||
if (ndiff < diff)
|
||||
{
|
||||
best_match = i;
|
||||
diff = ndiff;
|
||||
}
|
||||
}
|
||||
error = FT_Select_Size(face, best_match);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
glyph.face->set_character_sizes(glyph.format->text_size * scale_factor_);
|
||||
}
|
||||
|
||||
double size = glyph.format->text_size * scale_factor_;
|
||||
matrix.xx = static_cast<FT_Fixed>( glyph_pos.rot.cos * 0x10000L);
|
||||
matrix.xy = static_cast<FT_Fixed>(-glyph_pos.rot.sin * 0x10000L);
|
||||
matrix.yx = static_cast<FT_Fixed>( glyph_pos.rot.sin * 0x10000L);
|
||||
|
@ -77,17 +106,13 @@ void text_renderer::prepare_glyphs(glyph_positions const& positions)
|
|||
pen.x = static_cast<FT_Pos>(pos.x * 64);
|
||||
pen.y = static_cast<FT_Pos>(pos.y * 64);
|
||||
|
||||
FT_Face face = glyph.face->get_face();
|
||||
FT_Set_Transform(face, &matrix, &pen);
|
||||
|
||||
error = FT_Load_Glyph(face, glyph.glyph_index, FT_LOAD_NO_HINTING);
|
||||
error = FT_Load_Glyph(face, glyph.glyph_index, load_flags);
|
||||
if (error) continue;
|
||||
|
||||
FT_Glyph image;
|
||||
error = FT_Get_Glyph(face->glyph, &image);
|
||||
if (error) continue;
|
||||
|
||||
glyphs_.emplace_back(image, *glyph.format);
|
||||
glyphs_.emplace_back(image, *glyph.format, pos, size);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,7 +126,7 @@ void composite_bitmap(T & pixmap, FT_Bitmap *bitmap, unsigned rgba, int x, int y
|
|||
{
|
||||
for (int j = y, q = 0; j < y_max; ++j, ++q)
|
||||
{
|
||||
unsigned gray=bitmap->buffer[q*bitmap->width+p];
|
||||
unsigned gray = bitmap->buffer[q * bitmap->width + p];
|
||||
if (gray)
|
||||
{
|
||||
mapnik::composite_pixel(pixmap, comp_op, i, j, rgba, gray, opacity);
|
||||
|
@ -110,6 +135,31 @@ void composite_bitmap(T & pixmap, FT_Bitmap *bitmap, unsigned rgba, int x, int y
|
|||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void composite_color_bitmap(T & pixmap, FT_Bitmap *bitmap, int x, int y, double size, double opacity, composite_mode_e comp_op)
|
||||
{
|
||||
image_rgba8 image(bitmap->width, bitmap->rows);
|
||||
|
||||
for (unsigned i = 0, p = 0; i < bitmap->width; ++i, p += 4)
|
||||
{
|
||||
for (unsigned j = 0, q = 0; j < bitmap->rows; ++j, ++q)
|
||||
{
|
||||
std::uint8_t b = bitmap->buffer[q * bitmap->width * 4 + p];
|
||||
std::uint8_t g = bitmap->buffer[q * bitmap->width * 4 + p + 1];
|
||||
std::uint8_t r = bitmap->buffer[q * bitmap->width * 4 + p + 2];
|
||||
std::uint8_t a = bitmap->buffer[q * bitmap->width * 4 + p + 3];
|
||||
unsigned c = static_cast<unsigned>((a << 24) | (b << 16) | (g << 8) | (r));
|
||||
image(i, j) = c;
|
||||
}
|
||||
}
|
||||
double scale = size/image.height();
|
||||
int scaled_width = bitmap->width * scale;
|
||||
int scaled_height = bitmap->rows * scale;
|
||||
image_rgba8 scaled_image(scaled_width, scaled_height);
|
||||
scale_image_agg(scaled_image, image , SCALING_BILINEAR , scale, scale, 0.0, 0.0, 1.0, 0);
|
||||
composite(pixmap, scaled_image, comp_op, opacity, x, y);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
agg_text_renderer<T>::agg_text_renderer (pixmap_type & pixmap,
|
||||
halo_rasterizer_e rasterizer,
|
||||
|
@ -211,11 +261,30 @@ void agg_text_renderer<T>::render(glyph_positions const& pos)
|
|||
{
|
||||
fill = glyph.properties.fill.rgba();
|
||||
text_opacity = glyph.properties.text_opacity;
|
||||
|
||||
FT_Glyph_Transform(glyph.image, &matrix, &start);
|
||||
error = 0;
|
||||
if ( glyph.image->format != FT_GLYPH_FORMAT_BITMAP )
|
||||
{
|
||||
|
||||
error = FT_Glyph_To_Bitmap(&glyph.image ,FT_RENDER_MODE_NORMAL, 0, 1);
|
||||
if (!error)
|
||||
}
|
||||
if (error == 0)
|
||||
{
|
||||
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(glyph.image);
|
||||
int pixel_mode = bit->bitmap.pixel_mode;
|
||||
if (pixel_mode == 7)
|
||||
{
|
||||
int x = (start.x >> 6) + glyph.pos.x;
|
||||
int y = height - (start.y >> 6) + glyph.pos.y;
|
||||
composite_color_bitmap(pixmap_,
|
||||
&bit->bitmap,
|
||||
x,y, glyph.size,
|
||||
text_opacity,
|
||||
comp_op_);
|
||||
}
|
||||
else
|
||||
{
|
||||
composite_bitmap(pixmap_,
|
||||
&bit->bitmap,
|
||||
fill,
|
||||
|
@ -224,6 +293,7 @@ void agg_text_renderer<T>::render(glyph_positions const& pos)
|
|||
text_opacity,
|
||||
comp_op_);
|
||||
}
|
||||
}
|
||||
FT_Done_Glyph(glyph.image);
|
||||
}
|
||||
|
||||
|
@ -257,7 +327,6 @@ void grid_text_renderer<T>::render(glyph_positions const& pos, value_integer fea
|
|||
error = FT_Glyph_To_Bitmap(&glyph.image, FT_RENDER_MODE_NORMAL, 0, 1);
|
||||
if (!error)
|
||||
{
|
||||
|
||||
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(glyph.image);
|
||||
render_halo_id(&bit->bitmap,
|
||||
feature_id,
|
||||
|
|
Loading…
Reference in a new issue