parent
c7c10fed46
commit
d14203561d
10 changed files with 424 additions and 87 deletions
74
include/mapnik/text/color_font_renderer.hpp
Normal file
74
include/mapnik/text/color_font_renderer.hpp
Normal file
|
@ -0,0 +1,74 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* This file is part of Mapnik (c++ mapping toolkit)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 Artem Pavlenko
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MAPNIK_COLOR_FONT_RENDERER_HPP
|
||||||
|
#define MAPNIK_COLOR_FONT_RENDERER_HPP
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#include <mapnik/warning_ignore.hpp>
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#include <mapnik/warning_ignore_agg.hpp>
|
||||||
|
#include <agg_trans_affine.h>
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
// freetype2
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include <ft2build.h>
|
||||||
|
#include FT_FREETYPE_H
|
||||||
|
#include FT_STROKER_H
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
#include <mapnik/text/glyph_info.hpp>
|
||||||
|
#include <mapnik/image_any.hpp>
|
||||||
|
#include <mapnik/image_compositing.hpp>
|
||||||
|
#include <mapnik/geometry/box2d.hpp>
|
||||||
|
|
||||||
|
namespace mapnik
|
||||||
|
{
|
||||||
|
|
||||||
|
agg::trans_affine glyph_transform(agg::trans_affine const& tr,
|
||||||
|
unsigned glyph_height,
|
||||||
|
int x, int y,
|
||||||
|
double angle,
|
||||||
|
box2d<double> const& bbox);
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void composite_color_glyph(T & pixmap,
|
||||||
|
FT_Bitmap const& bitmap,
|
||||||
|
agg::trans_affine const& tr,
|
||||||
|
double opacity,
|
||||||
|
composite_mode_e comp_op);
|
||||||
|
|
||||||
|
struct glyph_t;
|
||||||
|
|
||||||
|
image_rgba8 render_glyph_image(glyph_t const& glyph,
|
||||||
|
FT_Bitmap const& bitmap,
|
||||||
|
agg::trans_affine const& tr,
|
||||||
|
pixel_position & render_pos);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -77,8 +77,10 @@ public:
|
||||||
~font_face();
|
~font_face();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool init_color_font();
|
||||||
|
|
||||||
FT_Face face_;
|
FT_Face face_;
|
||||||
bool color_font_ = false;
|
const bool color_font_;
|
||||||
};
|
};
|
||||||
using face_ptr = std::shared_ptr<font_face>;
|
using face_ptr = std::shared_ptr<font_face>;
|
||||||
|
|
||||||
|
|
|
@ -284,7 +284,7 @@ static void shape_text(text_line & line,
|
||||||
double tmp_height = g.height();
|
double tmp_height = g.height();
|
||||||
if (g.face->is_color())
|
if (g.face->is_color())
|
||||||
{
|
{
|
||||||
tmp_height = size;
|
tmp_height = g.ymax();
|
||||||
}
|
}
|
||||||
if (tmp_height > max_glyph_height) max_glyph_height = tmp_height;
|
if (tmp_height > max_glyph_height) max_glyph_height = tmp_height;
|
||||||
width_map[char_index] += g.advance();
|
width_map[char_index] += g.advance();
|
||||||
|
|
|
@ -29,11 +29,16 @@
|
||||||
#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>
|
#include <mapnik/pixel_position.hpp>
|
||||||
|
#include <mapnik/text/color_font_renderer.hpp>
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#include <mapnik/warning_ignore.hpp>
|
#include <mapnik/warning_ignore.hpp>
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#include <mapnik/warning_ignore_agg.hpp>
|
||||||
|
#include "agg_pixfmt_rgba.h"
|
||||||
#include <agg_trans_affine.h>
|
#include <agg_trans_affine.h>
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
// freetype2
|
// freetype2
|
||||||
extern "C"
|
extern "C"
|
||||||
|
@ -53,12 +58,21 @@ struct glyph_t
|
||||||
FT_Glyph image;
|
FT_Glyph image;
|
||||||
detail::evaluated_format_properties const& properties;
|
detail::evaluated_format_properties const& properties;
|
||||||
pixel_position pos;
|
pixel_position pos;
|
||||||
|
rotation rot;
|
||||||
double size;
|
double size;
|
||||||
glyph_t(FT_Glyph image_, detail::evaluated_format_properties const& properties_, pixel_position const& pos_, double size_)
|
box2d<double> bbox;
|
||||||
|
glyph_t(FT_Glyph image_,
|
||||||
|
detail::evaluated_format_properties const& properties_,
|
||||||
|
pixel_position const& pos_,
|
||||||
|
rotation const& rot_,
|
||||||
|
double size_,
|
||||||
|
box2d<double> const& bbox_)
|
||||||
: image(image_),
|
: image(image_),
|
||||||
properties(properties_),
|
properties(properties_),
|
||||||
pos(pos_),
|
pos(pos_),
|
||||||
size(size_) {}
|
rot(rot_),
|
||||||
|
size(size_),
|
||||||
|
bbox(bbox_) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class text_renderer : private util::noncopyable
|
class text_renderer : private util::noncopyable
|
||||||
|
@ -124,7 +138,12 @@ public:
|
||||||
void render(glyph_positions const& positions);
|
void render(glyph_positions const& positions);
|
||||||
private:
|
private:
|
||||||
pixmap_type & pixmap_;
|
pixmap_type & pixmap_;
|
||||||
void render_halo(FT_Bitmap_ *bitmap, unsigned rgba, int x, int y,
|
|
||||||
|
template <std::size_t PixelWidth>
|
||||||
|
void render_halo(unsigned char *buffer,
|
||||||
|
unsigned width,
|
||||||
|
unsigned height,
|
||||||
|
unsigned rgba, int x, int y,
|
||||||
double halo_radius, double opacity,
|
double halo_radius, double opacity,
|
||||||
composite_mode_e comp_op);
|
composite_mode_e comp_op);
|
||||||
};
|
};
|
||||||
|
@ -140,7 +159,14 @@ public:
|
||||||
void render(glyph_positions const& positions, value_integer feature_id);
|
void render(glyph_positions const& positions, value_integer feature_id);
|
||||||
private:
|
private:
|
||||||
pixmap_type & pixmap_;
|
pixmap_type & pixmap_;
|
||||||
void render_halo_id(FT_Bitmap_ *bitmap, mapnik::value_integer feature_id, int x, int y, int halo_radius);
|
|
||||||
|
template <std::size_t PixelWidth>
|
||||||
|
void render_halo_id(unsigned char *buffer,
|
||||||
|
unsigned width,
|
||||||
|
unsigned height,
|
||||||
|
mapnik::value_integer feature_id,
|
||||||
|
int x, int y,
|
||||||
|
int halo_radius);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,11 @@ struct rotation
|
||||||
double cos;
|
double cos;
|
||||||
rotation operator~() const { return rotation(sin, -cos); }
|
rotation operator~() const { return rotation(sin, -cos); }
|
||||||
rotation operator!() const { return rotation(-sin, cos); }
|
rotation operator!() const { return rotation(-sin, cos); }
|
||||||
|
|
||||||
|
double angle() const
|
||||||
|
{
|
||||||
|
return std::atan2(sin, cos);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -241,6 +241,7 @@ source = Split(
|
||||||
text/placement_finder.cpp
|
text/placement_finder.cpp
|
||||||
text/properties_util.cpp
|
text/properties_util.cpp
|
||||||
text/renderer.cpp
|
text/renderer.cpp
|
||||||
|
text/color_font_renderer.cpp
|
||||||
text/symbolizer_helpers.cpp
|
text/symbolizer_helpers.cpp
|
||||||
text/text_properties.cpp
|
text/text_properties.cpp
|
||||||
text/font_feature_settings.cpp
|
text/font_feature_settings.cpp
|
||||||
|
|
169
src/text/color_font_renderer.cpp
Normal file
169
src/text/color_font_renderer.cpp
Normal file
|
@ -0,0 +1,169 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* This file is part of Mapnik (c++ mapping toolkit)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2017 Artem Pavlenko
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
// mapnik
|
||||||
|
#include <mapnik/text/color_font_renderer.hpp>
|
||||||
|
#include <mapnik/text/renderer.hpp>
|
||||||
|
#include <mapnik/font_engine_freetype.hpp>
|
||||||
|
#include <mapnik/image_scaling.hpp>
|
||||||
|
#include <mapnik/text/face.hpp>
|
||||||
|
#include <mapnik/agg_rasterizer.hpp>
|
||||||
|
#include <mapnik/image_util.hpp>
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#include <mapnik/warning_ignore_agg.hpp>
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
#include "agg_color_rgba.h"
|
||||||
|
#include "agg_scanline_u.h"
|
||||||
|
#include "agg_image_filters.h"
|
||||||
|
#include "agg_trans_bilinear.h"
|
||||||
|
#include "agg_span_allocator.h"
|
||||||
|
#include "agg_image_accessors.h"
|
||||||
|
#include "agg_span_image_filter_rgba.h"
|
||||||
|
#include "agg_renderer_base.h"
|
||||||
|
#include "agg_renderer_scanline.h"
|
||||||
|
#include "agg_pixfmt_rgba.h"
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
|
namespace mapnik
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename Pixmap, typename ImageAccessor>
|
||||||
|
void composite_image(Pixmap & pixmap,
|
||||||
|
ImageAccessor & img_accessor,
|
||||||
|
double width,
|
||||||
|
double height,
|
||||||
|
agg::trans_affine const& tr,
|
||||||
|
double opacity,
|
||||||
|
composite_mode_e comp_op)
|
||||||
|
{
|
||||||
|
double p[8];
|
||||||
|
p[0] = 0; p[1] = 0;
|
||||||
|
p[2] = width; p[3] = 0;
|
||||||
|
p[4] = width; p[5] = height;
|
||||||
|
p[6] = 0; p[7] = height;
|
||||||
|
|
||||||
|
tr.transform(&p[0], &p[1]);
|
||||||
|
tr.transform(&p[2], &p[3]);
|
||||||
|
tr.transform(&p[4], &p[5]);
|
||||||
|
tr.transform(&p[6], &p[7]);
|
||||||
|
|
||||||
|
rasterizer ras;
|
||||||
|
ras.move_to_d(p[0], p[1]);
|
||||||
|
ras.line_to_d(p[2], p[3]);
|
||||||
|
ras.line_to_d(p[4], p[5]);
|
||||||
|
ras.line_to_d(p[6], p[7]);
|
||||||
|
|
||||||
|
using color_type = agg::rgba8;
|
||||||
|
using order_type = agg::order_rgba;
|
||||||
|
using blender_type = agg::comp_op_adaptor_rgba_pre<color_type, order_type>;
|
||||||
|
using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
|
||||||
|
using renderer_base = agg::renderer_base<pixfmt_comp_type>;
|
||||||
|
|
||||||
|
agg::scanline_u8 sl;
|
||||||
|
agg::rendering_buffer buf(pixmap.bytes(),
|
||||||
|
pixmap.width(),
|
||||||
|
pixmap.height(),
|
||||||
|
pixmap.row_size());
|
||||||
|
pixfmt_comp_type pixf(buf);
|
||||||
|
pixf.comp_op(static_cast<agg::comp_op_e>(comp_op));
|
||||||
|
renderer_base renb(pixf);
|
||||||
|
|
||||||
|
agg::span_allocator<color_type> sa;
|
||||||
|
agg::image_filter_bilinear filter_kernel;
|
||||||
|
agg::image_filter_lut filter(filter_kernel, false);
|
||||||
|
|
||||||
|
using interpolator_type = agg::span_interpolator_linear<agg::trans_affine>;
|
||||||
|
using span_gen_type = agg::span_image_resample_rgba_affine<ImageAccessor>;
|
||||||
|
using renderer_type = agg::renderer_scanline_aa_alpha<renderer_base,
|
||||||
|
agg::span_allocator<agg::rgba8>,
|
||||||
|
span_gen_type>;
|
||||||
|
agg::trans_affine final_tr(p, 0, 0, width, height);
|
||||||
|
final_tr.tx = std::floor(final_tr.tx + .5);
|
||||||
|
final_tr.ty = std::floor(final_tr.ty + .5);
|
||||||
|
interpolator_type interpolator(final_tr);
|
||||||
|
span_gen_type sg(img_accessor, interpolator, filter);
|
||||||
|
renderer_type rp(renb,sa, sg, static_cast<unsigned>(opacity * 255));
|
||||||
|
agg::render_scanlines(ras, sl, rp);
|
||||||
|
}
|
||||||
|
|
||||||
|
agg::trans_affine glyph_transform(agg::trans_affine const& tr,
|
||||||
|
unsigned glyph_height,
|
||||||
|
int x, int y,
|
||||||
|
double angle,
|
||||||
|
box2d<double> const& bbox)
|
||||||
|
{
|
||||||
|
agg::trans_affine t;
|
||||||
|
double scale = bbox.height() / glyph_height;
|
||||||
|
t *= agg::trans_affine_translation(0, -bbox.maxy() / scale); // set to baseline
|
||||||
|
t *= tr;
|
||||||
|
t *= agg::trans_affine_rotation(angle);
|
||||||
|
t *= agg::trans_affine_scaling(scale);
|
||||||
|
t *= agg::trans_affine_translation(x, y);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void composite_color_glyph(T & pixmap,
|
||||||
|
FT_Bitmap const& bitmap,
|
||||||
|
agg::trans_affine const& tr,
|
||||||
|
double opacity,
|
||||||
|
composite_mode_e comp_op)
|
||||||
|
{
|
||||||
|
using glyph_pixfmt_type = agg::pixfmt_bgra32_pre;
|
||||||
|
using img_accessor_type = agg::image_accessor_clone<glyph_pixfmt_type>;
|
||||||
|
unsigned width = bitmap.width;
|
||||||
|
unsigned height = bitmap.rows;
|
||||||
|
agg::rendering_buffer glyph_buf(bitmap.buffer, width, height, width * glyph_pixfmt_type::pix_width);
|
||||||
|
glyph_pixfmt_type glyph_pixf(glyph_buf);
|
||||||
|
img_accessor_type img_accessor(glyph_pixf);
|
||||||
|
|
||||||
|
composite_image<T, img_accessor_type>(
|
||||||
|
pixmap, img_accessor, width, height, tr,
|
||||||
|
opacity, comp_op);
|
||||||
|
}
|
||||||
|
|
||||||
|
template
|
||||||
|
void composite_color_glyph<image_rgba8>(image_rgba8 & pixmap,
|
||||||
|
FT_Bitmap const& bitmap,
|
||||||
|
agg::trans_affine const& tr,
|
||||||
|
double opacity,
|
||||||
|
composite_mode_e comp_op);
|
||||||
|
|
||||||
|
image_rgba8 render_glyph_image(glyph_t const& glyph,
|
||||||
|
FT_Bitmap const& bitmap,
|
||||||
|
agg::trans_affine const& tr,
|
||||||
|
pixel_position & render_pos)
|
||||||
|
{
|
||||||
|
agg::trans_affine transform(glyph_transform(tr, bitmap.rows, 0, 0, -glyph.rot.angle(), glyph.bbox));
|
||||||
|
box2d<double> bitmap_bbox(0, 0, bitmap.width, bitmap.rows);
|
||||||
|
bitmap_bbox *= transform;
|
||||||
|
image_rgba8 glyph_image(bitmap_bbox.width(), bitmap_bbox.height());
|
||||||
|
transform *= agg::trans_affine_translation(-bitmap_bbox.minx(), -bitmap_bbox.miny());
|
||||||
|
render_pos = render_pos +
|
||||||
|
pixel_position(glyph.pos.x, -glyph.pos.y) +
|
||||||
|
pixel_position(std::round(bitmap_bbox.minx()), std::round(bitmap_bbox.miny()));
|
||||||
|
composite_color_glyph(glyph_image, bitmap, transform, 1, dst_over);
|
||||||
|
return glyph_image;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace mapnik
|
|
@ -38,12 +38,17 @@ namespace mapnik
|
||||||
{
|
{
|
||||||
|
|
||||||
font_face::font_face(FT_Face face)
|
font_face::font_face(FT_Face face)
|
||||||
: face_(face)
|
: face_(face),
|
||||||
|
color_font_(init_color_font())
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool font_face::init_color_font()
|
||||||
{
|
{
|
||||||
static const uint32_t tag = FT_MAKE_TAG('C', 'B', 'D', 'T');
|
static const uint32_t tag = FT_MAKE_TAG('C', 'B', 'D', 'T');
|
||||||
unsigned long length = 0;
|
unsigned long length = 0;
|
||||||
FT_Load_Sfnt_Table(face_, tag, 0, nullptr, &length);
|
FT_Load_Sfnt_Table(face_, tag, 0, nullptr, &length);
|
||||||
if (length) color_font_ = true;
|
return length > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool font_face::set_character_sizes(double size)
|
bool font_face::set_character_sizes(double size)
|
||||||
|
@ -85,6 +90,15 @@ bool font_face::glyph_dimensions(glyph_info & glyph) const
|
||||||
glyph.unscaled_ymax = glyph_bbox.yMax;
|
glyph.unscaled_ymax = glyph_bbox.yMax;
|
||||||
glyph.unscaled_advance = face_->glyph->advance.x;
|
glyph.unscaled_advance = face_->glyph->advance.x;
|
||||||
glyph.unscaled_line_height = face_->size->metrics.height;
|
glyph.unscaled_line_height = face_->size->metrics.height;
|
||||||
|
|
||||||
|
if (color_font_)
|
||||||
|
{
|
||||||
|
double scale_multiplier = 2048.0 / (face_->size->metrics.height);
|
||||||
|
glyph.unscaled_ymin *= scale_multiplier;
|
||||||
|
glyph.unscaled_ymax *= scale_multiplier;
|
||||||
|
glyph.unscaled_advance *= scale_multiplier;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,22 @@
|
||||||
#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>
|
||||||
|
#include <mapnik/agg_rasterizer.hpp>
|
||||||
|
|
||||||
|
#pragma GCC diagnostic push
|
||||||
|
#include <mapnik/warning_ignore_agg.hpp>
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
#include "agg_pixfmt_rgba.h"
|
||||||
|
#include "agg_color_rgba.h"
|
||||||
|
#include "agg_scanline_u.h"
|
||||||
|
#include "agg_image_filters.h"
|
||||||
|
#include "agg_trans_bilinear.h"
|
||||||
|
#include "agg_span_allocator.h"
|
||||||
|
#include "agg_image_accessors.h"
|
||||||
|
#include "agg_span_image_filter_rgba.h"
|
||||||
|
#include "agg_renderer_base.h"
|
||||||
|
#include "agg_renderer_scanline.h"
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
|
||||||
namespace mapnik
|
namespace mapnik
|
||||||
{
|
{
|
||||||
|
@ -112,7 +128,8 @@ void text_renderer::prepare_glyphs(glyph_positions const& positions)
|
||||||
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);
|
box2d<double> bbox(0, glyph_pos.glyph.ymin(), glyph_pos.glyph.advance(), glyph_pos.glyph.ymax());
|
||||||
|
glyphs_.emplace_back(image, *glyph.format, pos, glyph_pos.rot, size, bbox);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,32 +152,6 @@ 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);
|
|
||||||
set_premultiplied_alpha(scaled_image, true);
|
|
||||||
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,
|
||||||
|
@ -229,28 +220,58 @@ void agg_text_renderer<T>::render(glyph_positions const& pos)
|
||||||
if (!error)
|
if (!error)
|
||||||
{
|
{
|
||||||
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(g);
|
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(g);
|
||||||
composite_bitmap(pixmap_,
|
if (bit->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
|
||||||
&bit->bitmap,
|
{
|
||||||
halo_fill,
|
continue;
|
||||||
bit->left,
|
}
|
||||||
height - bit->top,
|
else
|
||||||
halo_opacity,
|
{
|
||||||
halo_comp_op_);
|
composite_bitmap(pixmap_,
|
||||||
|
&bit->bitmap,
|
||||||
|
halo_fill,
|
||||||
|
bit->left,
|
||||||
|
height - bit->top,
|
||||||
|
halo_opacity,
|
||||||
|
halo_comp_op_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error = FT_Glyph_To_Bitmap(&g, FT_RENDER_MODE_NORMAL, 0, 1);
|
error = FT_Glyph_To_Bitmap(&g, FT_RENDER_MODE_NORMAL, 0, 1);
|
||||||
if (!error)
|
if (error)
|
||||||
{
|
{
|
||||||
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(g);
|
continue;
|
||||||
render_halo(&bit->bitmap,
|
}
|
||||||
halo_fill,
|
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(g);
|
||||||
bit->left,
|
if (bit->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
|
||||||
height - bit->top,
|
{
|
||||||
halo_radius,
|
pixel_position render_pos(base_point);
|
||||||
halo_opacity,
|
image_rgba8 glyph_image(render_glyph_image(glyph,
|
||||||
halo_comp_op_);
|
bit->bitmap,
|
||||||
|
transform_,
|
||||||
|
render_pos));
|
||||||
|
const constexpr std::size_t pixel_size = sizeof(image_rgba8::pixel_type);
|
||||||
|
render_halo<pixel_size>(glyph_image.bytes(),
|
||||||
|
glyph_image.width(),
|
||||||
|
glyph_image.height(),
|
||||||
|
halo_fill,
|
||||||
|
render_pos.x, render_pos.y,
|
||||||
|
halo_radius,
|
||||||
|
halo_opacity,
|
||||||
|
halo_comp_op_);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
render_halo<1>(bit->bitmap.buffer,
|
||||||
|
bit->bitmap.width,
|
||||||
|
bit->bitmap.rows,
|
||||||
|
halo_fill,
|
||||||
|
bit->left,
|
||||||
|
height - bit->top,
|
||||||
|
halo_radius,
|
||||||
|
halo_opacity,
|
||||||
|
halo_comp_op_);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -267,22 +288,27 @@ void agg_text_renderer<T>::render(glyph_positions const& pos)
|
||||||
error = 0;
|
error = 0;
|
||||||
if ( glyph.image->format != FT_GLYPH_FORMAT_BITMAP )
|
if ( glyph.image->format != FT_GLYPH_FORMAT_BITMAP )
|
||||||
{
|
{
|
||||||
|
|
||||||
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 == 0)
|
if (error == 0)
|
||||||
{
|
{
|
||||||
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(glyph.image);
|
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(glyph.image);
|
||||||
int pixel_mode = bit->bitmap.pixel_mode;
|
int pixel_mode = bit->bitmap.pixel_mode;
|
||||||
if (pixel_mode == 7)
|
if (pixel_mode == FT_PIXEL_MODE_BGRA)
|
||||||
{
|
{
|
||||||
int x = (start.x >> 6) + glyph.pos.x;
|
int x = base_point.x + glyph.pos.x;
|
||||||
int y = height - (start.y >> 6) + glyph.pos.y;
|
int y = base_point.y - glyph.pos.y;
|
||||||
composite_color_bitmap(pixmap_,
|
agg::trans_affine transform(
|
||||||
&bit->bitmap,
|
glyph_transform(transform_,
|
||||||
x,y, glyph.size,
|
bit->bitmap.rows,
|
||||||
text_opacity,
|
x, y,
|
||||||
comp_op_);
|
-glyph.rot.angle(),
|
||||||
|
glyph.bbox));
|
||||||
|
composite_color_glyph(pixmap_,
|
||||||
|
bit->bitmap,
|
||||||
|
transform,
|
||||||
|
text_opacity,
|
||||||
|
comp_op_);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -300,7 +326,6 @@ void agg_text_renderer<T>::render(glyph_positions const& pos)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void grid_text_renderer<T>::render(glyph_positions const& pos, value_integer feature_id)
|
void grid_text_renderer<T>::render(glyph_positions const& pos, value_integer feature_id)
|
||||||
{
|
{
|
||||||
|
@ -329,11 +354,31 @@ void grid_text_renderer<T>::render(glyph_positions const& pos, value_integer fea
|
||||||
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,
|
if (bit->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
|
||||||
feature_id,
|
{
|
||||||
bit->left,
|
pixel_position render_pos(base_point);
|
||||||
height - bit->top,
|
image_rgba8 glyph_image(render_glyph_image(glyph,
|
||||||
static_cast<int>(halo_radius));
|
bit->bitmap,
|
||||||
|
transform_,
|
||||||
|
render_pos));
|
||||||
|
const constexpr std::size_t pixel_size = sizeof(image_rgba8::pixel_type);
|
||||||
|
render_halo_id<pixel_size>(glyph_image.bytes(),
|
||||||
|
glyph_image.width(),
|
||||||
|
glyph_image.height(),
|
||||||
|
feature_id,
|
||||||
|
render_pos.x, render_pos.y,
|
||||||
|
static_cast<int>(halo_radius));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
render_halo_id<1>(bit->bitmap.buffer,
|
||||||
|
bit->bitmap.width,
|
||||||
|
bit->bitmap.rows,
|
||||||
|
feature_id,
|
||||||
|
bit->left,
|
||||||
|
height - bit->top,
|
||||||
|
static_cast<int>(halo_radius));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
FT_Done_Glyph(glyph.image);
|
FT_Done_Glyph(glyph.image);
|
||||||
}
|
}
|
||||||
|
@ -341,16 +386,17 @@ void grid_text_renderer<T>::render(glyph_positions const& pos, value_integer fea
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void agg_text_renderer<T>::render_halo(FT_Bitmap *bitmap,
|
template <std::size_t PixelWidth>
|
||||||
unsigned rgba,
|
void agg_text_renderer<T>::render_halo(unsigned char *buffer,
|
||||||
int x1,
|
unsigned width,
|
||||||
int y1,
|
unsigned height,
|
||||||
double halo_radius,
|
unsigned rgba,
|
||||||
double opacity,
|
int x1,
|
||||||
composite_mode_e comp_op)
|
int y1,
|
||||||
|
double halo_radius,
|
||||||
|
double opacity,
|
||||||
|
composite_mode_e comp_op)
|
||||||
{
|
{
|
||||||
int width = bitmap->width;
|
|
||||||
int height = bitmap->rows;
|
|
||||||
int x, y;
|
int x, y;
|
||||||
if (halo_radius < 1.0)
|
if (halo_radius < 1.0)
|
||||||
{
|
{
|
||||||
|
@ -358,7 +404,7 @@ void agg_text_renderer<T>::render_halo(FT_Bitmap *bitmap,
|
||||||
{
|
{
|
||||||
for (y=0; y < height; y++)
|
for (y=0; y < height; y++)
|
||||||
{
|
{
|
||||||
int gray = bitmap->buffer[y*bitmap->width+x];
|
int gray = buffer[(y * width + x) * PixelWidth + PixelWidth - 1];
|
||||||
if (gray)
|
if (gray)
|
||||||
{
|
{
|
||||||
mapnik::composite_pixel(pixmap_, comp_op, x+x1-1, y+y1-1, rgba, gray*halo_radius*halo_radius, opacity);
|
mapnik::composite_pixel(pixmap_, comp_op, x+x1-1, y+y1-1, rgba, gray*halo_radius*halo_radius, opacity);
|
||||||
|
@ -382,7 +428,7 @@ void agg_text_renderer<T>::render_halo(FT_Bitmap *bitmap,
|
||||||
{
|
{
|
||||||
for (y=0; y < height; y++)
|
for (y=0; y < height; y++)
|
||||||
{
|
{
|
||||||
int gray = bitmap->buffer[y*bitmap->width+x];
|
int gray = buffer[(y * width + x) * PixelWidth + PixelWidth - 1];
|
||||||
if (gray)
|
if (gray)
|
||||||
{
|
{
|
||||||
for (int n=-halo_radius; n <=halo_radius; ++n)
|
for (int n=-halo_radius; n <=halo_radius; ++n)
|
||||||
|
@ -395,21 +441,21 @@ void agg_text_renderer<T>::render_halo(FT_Bitmap *bitmap,
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void grid_text_renderer<T>::render_halo_id(
|
template <std::size_t PixelWidth>
|
||||||
FT_Bitmap *bitmap,
|
void grid_text_renderer<T>::render_halo_id(unsigned char *buffer,
|
||||||
mapnik::value_integer feature_id,
|
unsigned width,
|
||||||
int x1,
|
unsigned height,
|
||||||
int y1,
|
mapnik::value_integer feature_id,
|
||||||
int halo_radius)
|
int x1,
|
||||||
|
int y1,
|
||||||
|
int halo_radius)
|
||||||
{
|
{
|
||||||
int width = bitmap->width;
|
|
||||||
int height = bitmap->rows;
|
|
||||||
int x, y;
|
int x, y;
|
||||||
for (x=0; x < width; x++)
|
for (x=0; x < width; x++)
|
||||||
{
|
{
|
||||||
for (y=0; y < height; y++)
|
for (y=0; y < height; y++)
|
||||||
{
|
{
|
||||||
int gray = bitmap->buffer[y*bitmap->width+x];
|
int gray = buffer[(y * width + x) * PixelWidth + PixelWidth - 1];
|
||||||
if (gray)
|
if (gray)
|
||||||
{
|
{
|
||||||
for (int n=-halo_radius; n <=halo_radius; ++n)
|
for (int n=-halo_radius; n <=halo_radius; ++n)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit df578e3436681bb9bc582c7ac55a4205e98334f4
|
Subproject commit 114faca337e6dd1a0b31f30c285f8f4c29915e09
|
Loading…
Reference in a new issue