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/image_compositing.hpp>
|
||||||
#include <mapnik/symbolizer_enumerations.hpp>
|
#include <mapnik/symbolizer_enumerations.hpp>
|
||||||
#include <mapnik/util/noncopyable.hpp>
|
#include <mapnik/util/noncopyable.hpp>
|
||||||
|
#include <mapnik/pixel_position.hpp>
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#include <mapnik/warning_ignore.hpp>
|
#include <mapnik/warning_ignore.hpp>
|
||||||
|
@ -51,8 +52,13 @@ struct glyph_t
|
||||||
{
|
{
|
||||||
FT_Glyph image;
|
FT_Glyph image;
|
||||||
detail::evaluated_format_properties const& properties;
|
detail::evaluated_format_properties const& properties;
|
||||||
glyph_t(FT_Glyph image_, detail::evaluated_format_properties const& properties_)
|
pixel_position pos;
|
||||||
: image(image_), properties(properties_) {}
|
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
|
class text_renderer : private util::noncopyable
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
#include <mapnik/grid/grid.hpp>
|
#include <mapnik/grid/grid.hpp>
|
||||||
#include <mapnik/text/text_properties.hpp>
|
#include <mapnik/text/text_properties.hpp>
|
||||||
#include <mapnik/font_engine_freetype.hpp>
|
#include <mapnik/font_engine_freetype.hpp>
|
||||||
|
#include <mapnik/image_compositing.hpp>
|
||||||
|
#include <mapnik/image_scaling.hpp>
|
||||||
#include <mapnik/text/face.hpp>
|
#include <mapnik/text/face.hpp>
|
||||||
#include <mapnik/image_util.hpp>
|
#include <mapnik/image_util.hpp>
|
||||||
#include <mapnik/image_any.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)
|
for (auto const& glyph_pos : positions)
|
||||||
{
|
{
|
||||||
glyph_info const& glyph = glyph_pos.glyph;
|
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.xx = static_cast<FT_Fixed>( glyph_pos.rot.cos * 0x10000L);
|
||||||
matrix.xy = static_cast<FT_Fixed>(-glyph_pos.rot.sin * 0x10000L);
|
matrix.xy = static_cast<FT_Fixed>(-glyph_pos.rot.sin * 0x10000L);
|
||||||
matrix.yx = 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.x = static_cast<FT_Pos>(pos.x * 64);
|
||||||
pen.y = static_cast<FT_Pos>(pos.y * 64);
|
pen.y = static_cast<FT_Pos>(pos.y * 64);
|
||||||
|
|
||||||
FT_Face face = glyph.face->get_face();
|
|
||||||
FT_Set_Transform(face, &matrix, &pen);
|
FT_Set_Transform(face, &matrix, &pen);
|
||||||
|
error = FT_Load_Glyph(face, glyph.glyph_index, load_flags);
|
||||||
error = FT_Load_Glyph(face, glyph.glyph_index, FT_LOAD_NO_HINTING);
|
|
||||||
if (error) continue;
|
if (error) continue;
|
||||||
|
|
||||||
FT_Glyph image;
|
FT_Glyph image;
|
||||||
error = FT_Get_Glyph(face->glyph, &image);
|
error = FT_Get_Glyph(face->glyph, &image);
|
||||||
if (error) continue;
|
if (error) continue;
|
||||||
|
glyphs_.emplace_back(image, *glyph.format, pos, size);
|
||||||
glyphs_.emplace_back(image, *glyph.format);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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)
|
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)
|
if (gray)
|
||||||
{
|
{
|
||||||
mapnik::composite_pixel(pixmap, comp_op, i, j, rgba, gray, opacity);
|
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>
|
template <typename T>
|
||||||
agg_text_renderer<T>::agg_text_renderer (pixmap_type & pixmap,
|
agg_text_renderer<T>::agg_text_renderer (pixmap_type & pixmap,
|
||||||
halo_rasterizer_e rasterizer,
|
halo_rasterizer_e rasterizer,
|
||||||
|
@ -211,18 +261,38 @@ void agg_text_renderer<T>::render(glyph_positions const& pos)
|
||||||
{
|
{
|
||||||
fill = glyph.properties.fill.rgba();
|
fill = glyph.properties.fill.rgba();
|
||||||
text_opacity = glyph.properties.text_opacity;
|
text_opacity = glyph.properties.text_opacity;
|
||||||
|
|
||||||
FT_Glyph_Transform(glyph.image, &matrix, &start);
|
FT_Glyph_Transform(glyph.image, &matrix, &start);
|
||||||
error = FT_Glyph_To_Bitmap(&glyph.image ,FT_RENDER_MODE_NORMAL, 0, 1);
|
error = 0;
|
||||||
if (!error)
|
if ( glyph.image->format != FT_GLYPH_FORMAT_BITMAP )
|
||||||
|
{
|
||||||
|
|
||||||
|
error = FT_Glyph_To_Bitmap(&glyph.image ,FT_RENDER_MODE_NORMAL, 0, 1);
|
||||||
|
}
|
||||||
|
if (error == 0)
|
||||||
{
|
{
|
||||||
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(glyph.image);
|
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(glyph.image);
|
||||||
composite_bitmap(pixmap_,
|
int pixel_mode = bit->bitmap.pixel_mode;
|
||||||
&bit->bitmap,
|
if (pixel_mode == 7)
|
||||||
fill,
|
{
|
||||||
bit->left,
|
int x = (start.x >> 6) + glyph.pos.x;
|
||||||
height - bit->top,
|
int y = height - (start.y >> 6) + glyph.pos.y;
|
||||||
text_opacity,
|
composite_color_bitmap(pixmap_,
|
||||||
comp_op_);
|
&bit->bitmap,
|
||||||
|
x,y, glyph.size,
|
||||||
|
text_opacity,
|
||||||
|
comp_op_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
composite_bitmap(pixmap_,
|
||||||
|
&bit->bitmap,
|
||||||
|
fill,
|
||||||
|
bit->left,
|
||||||
|
height - bit->top,
|
||||||
|
text_opacity,
|
||||||
|
comp_op_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FT_Done_Glyph(glyph.image);
|
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);
|
error = FT_Glyph_To_Bitmap(&glyph.image, FT_RENDER_MODE_NORMAL, 0, 1);
|
||||||
if (!error)
|
if (!error)
|
||||||
{
|
{
|
||||||
|
|
||||||
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(glyph.image);
|
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(glyph.image);
|
||||||
render_halo_id(&bit->bitmap,
|
render_halo_id(&bit->bitmap,
|
||||||
feature_id,
|
feature_id,
|
||||||
|
|
Loading…
Add table
Reference in a new issue