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();
|
||||
|
||||
private:
|
||||
bool init_color_font();
|
||||
|
||||
FT_Face face_;
|
||||
bool color_font_ = false;
|
||||
const bool color_font_;
|
||||
};
|
||||
using face_ptr = std::shared_ptr<font_face>;
|
||||
|
||||
|
|
|
@ -284,7 +284,7 @@ static void shape_text(text_line & line,
|
|||
double tmp_height = g.height();
|
||||
if (g.face->is_color())
|
||||
{
|
||||
tmp_height = size;
|
||||
tmp_height = g.ymax();
|
||||
}
|
||||
if (tmp_height > max_glyph_height) max_glyph_height = tmp_height;
|
||||
width_map[char_index] += g.advance();
|
||||
|
|
|
@ -29,11 +29,16 @@
|
|||
#include <mapnik/symbolizer_enumerations.hpp>
|
||||
#include <mapnik/util/noncopyable.hpp>
|
||||
#include <mapnik/pixel_position.hpp>
|
||||
#include <mapnik/text/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_pixfmt_rgba.h"
|
||||
#include <agg_trans_affine.h>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
// freetype2
|
||||
extern "C"
|
||||
|
@ -53,12 +58,21 @@ struct glyph_t
|
|||
FT_Glyph image;
|
||||
detail::evaluated_format_properties const& properties;
|
||||
pixel_position pos;
|
||||
rotation rot;
|
||||
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_),
|
||||
properties(properties_),
|
||||
pos(pos_),
|
||||
size(size_) {}
|
||||
rot(rot_),
|
||||
size(size_),
|
||||
bbox(bbox_) {}
|
||||
};
|
||||
|
||||
class text_renderer : private util::noncopyable
|
||||
|
@ -124,7 +138,12 @@ public:
|
|||
void render(glyph_positions const& positions);
|
||||
private:
|
||||
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,
|
||||
composite_mode_e comp_op);
|
||||
};
|
||||
|
@ -140,7 +159,14 @@ public:
|
|||
void render(glyph_positions const& positions, value_integer feature_id);
|
||||
private:
|
||||
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;
|
||||
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/properties_util.cpp
|
||||
text/renderer.cpp
|
||||
text/color_font_renderer.cpp
|
||||
text/symbolizer_helpers.cpp
|
||||
text/text_properties.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)
|
||||
: 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');
|
||||
unsigned long length = 0;
|
||||
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)
|
||||
|
@ -85,6 +90,15 @@ bool font_face::glyph_dimensions(glyph_info & glyph) const
|
|||
glyph.unscaled_ymax = glyph_bbox.yMax;
|
||||
glyph.unscaled_advance = face_->glyph->advance.x;
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,22 @@
|
|||
#include <mapnik/text/face.hpp>
|
||||
#include <mapnik/image_util.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
|
||||
{
|
||||
|
@ -112,7 +128,8 @@ void text_renderer::prepare_glyphs(glyph_positions const& positions)
|
|||
FT_Glyph image;
|
||||
error = FT_Get_Glyph(face->glyph, &image);
|
||||
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>
|
||||
agg_text_renderer<T>::agg_text_renderer (pixmap_type & pixmap,
|
||||
halo_rasterizer_e rasterizer,
|
||||
|
@ -229,28 +220,58 @@ void agg_text_renderer<T>::render(glyph_positions const& pos)
|
|||
if (!error)
|
||||
{
|
||||
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(g);
|
||||
composite_bitmap(pixmap_,
|
||||
&bit->bitmap,
|
||||
halo_fill,
|
||||
bit->left,
|
||||
height - bit->top,
|
||||
halo_opacity,
|
||||
halo_comp_op_);
|
||||
if (bit->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
composite_bitmap(pixmap_,
|
||||
&bit->bitmap,
|
||||
halo_fill,
|
||||
bit->left,
|
||||
height - bit->top,
|
||||
halo_opacity,
|
||||
halo_comp_op_);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error = FT_Glyph_To_Bitmap(&g, FT_RENDER_MODE_NORMAL, 0, 1);
|
||||
if (!error)
|
||||
if (error)
|
||||
{
|
||||
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(g);
|
||||
render_halo(&bit->bitmap,
|
||||
halo_fill,
|
||||
bit->left,
|
||||
height - bit->top,
|
||||
halo_radius,
|
||||
halo_opacity,
|
||||
halo_comp_op_);
|
||||
continue;
|
||||
}
|
||||
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(g);
|
||||
if (bit->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
|
||||
{
|
||||
pixel_position render_pos(base_point);
|
||||
image_rgba8 glyph_image(render_glyph_image(glyph,
|
||||
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;
|
||||
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);
|
||||
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 y = height - (start.y >> 6) + glyph.pos.y;
|
||||
composite_color_bitmap(pixmap_,
|
||||
&bit->bitmap,
|
||||
x,y, glyph.size,
|
||||
text_opacity,
|
||||
comp_op_);
|
||||
int x = base_point.x + glyph.pos.x;
|
||||
int y = base_point.y - glyph.pos.y;
|
||||
agg::trans_affine transform(
|
||||
glyph_transform(transform_,
|
||||
bit->bitmap.rows,
|
||||
x, y,
|
||||
-glyph.rot.angle(),
|
||||
glyph.bbox));
|
||||
composite_color_glyph(pixmap_,
|
||||
bit->bitmap,
|
||||
transform,
|
||||
text_opacity,
|
||||
comp_op_);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -300,7 +326,6 @@ void agg_text_renderer<T>::render(glyph_positions const& pos)
|
|||
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
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)
|
||||
{
|
||||
FT_BitmapGlyph bit = reinterpret_cast<FT_BitmapGlyph>(glyph.image);
|
||||
render_halo_id(&bit->bitmap,
|
||||
feature_id,
|
||||
bit->left,
|
||||
height - bit->top,
|
||||
static_cast<int>(halo_radius));
|
||||
if (bit->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA)
|
||||
{
|
||||
pixel_position render_pos(base_point);
|
||||
image_rgba8 glyph_image(render_glyph_image(glyph,
|
||||
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);
|
||||
}
|
||||
|
@ -341,16 +386,17 @@ void grid_text_renderer<T>::render(glyph_positions const& pos, value_integer fea
|
|||
|
||||
|
||||
template <typename T>
|
||||
void agg_text_renderer<T>::render_halo(FT_Bitmap *bitmap,
|
||||
unsigned rgba,
|
||||
int x1,
|
||||
int y1,
|
||||
double halo_radius,
|
||||
double opacity,
|
||||
composite_mode_e comp_op)
|
||||
template <std::size_t PixelWidth>
|
||||
void agg_text_renderer<T>::render_halo(unsigned char *buffer,
|
||||
unsigned width,
|
||||
unsigned height,
|
||||
unsigned rgba,
|
||||
int x1,
|
||||
int y1,
|
||||
double halo_radius,
|
||||
double opacity,
|
||||
composite_mode_e comp_op)
|
||||
{
|
||||
int width = bitmap->width;
|
||||
int height = bitmap->rows;
|
||||
int x, y;
|
||||
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++)
|
||||
{
|
||||
int gray = bitmap->buffer[y*bitmap->width+x];
|
||||
int gray = buffer[(y * width + x) * PixelWidth + PixelWidth - 1];
|
||||
if (gray)
|
||||
{
|
||||
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++)
|
||||
{
|
||||
int gray = bitmap->buffer[y*bitmap->width+x];
|
||||
int gray = buffer[(y * width + x) * PixelWidth + PixelWidth - 1];
|
||||
if (gray)
|
||||
{
|
||||
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>
|
||||
void grid_text_renderer<T>::render_halo_id(
|
||||
FT_Bitmap *bitmap,
|
||||
mapnik::value_integer feature_id,
|
||||
int x1,
|
||||
int y1,
|
||||
int halo_radius)
|
||||
template <std::size_t PixelWidth>
|
||||
void grid_text_renderer<T>::render_halo_id(unsigned char *buffer,
|
||||
unsigned width,
|
||||
unsigned height,
|
||||
mapnik::value_integer feature_id,
|
||||
int x1,
|
||||
int y1,
|
||||
int halo_radius)
|
||||
{
|
||||
int width = bitmap->width;
|
||||
int height = bitmap->rows;
|
||||
int x, y;
|
||||
for (x=0; x < width; x++)
|
||||
{
|
||||
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)
|
||||
{
|
||||
for (int n=-halo_radius; n <=halo_radius; ++n)
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit df578e3436681bb9bc582c7ac55a4205e98334f4
|
||||
Subproject commit 114faca337e6dd1a0b31f30c285f8f4c29915e09
|
Loading…
Reference in a new issue