Commit d738e505 authored by Paul Asmuth's avatar Paul Asmuth
Browse files

rudimentary glyph rasterization using freetype

parent 46d6b475
Loading
Loading
Loading
Loading
+23 −23
Original line number Diff line number Diff line
@@ -17,34 +17,34 @@ void strokePath(
    const PathData* point_data,
    size_t point_count,
    const StrokeStyle& style) {
  auto ctx = layer->rasterizer.ctx;
  //auto ctx = layer->rasterizer.ctx;

  if (point_count < 2) {
    return;
  }
  //if (point_count < 2) {
  //  return;
  //}

  cairo_set_source_rgba(
      ctx,
      style.colour.red(),
      style.colour.green(),
      style.colour.blue(),
      style.colour.alpha());
  //cairo_set_source_rgba(
  //    ctx,
  //    style.colour.red(),
  //    style.colour.green(),
  //    style.colour.blue(),
  //    style.colour.alpha());

  cairo_set_line_width(ctx, style.line_width);
  //cairo_set_line_width(ctx, style.line_width);

  for (size_t i = 0; i < point_count; ++i) {
    const auto& cmd = point_data[i];
    switch (cmd.command) {
      case PathCommand::MOVE_TO:
        cairo_move_to(ctx, cmd[0], cmd[1]);
        break;
      case PathCommand::LINE_TO:
        cairo_line_to(ctx, cmd[0], cmd[1]);
        break;
    }
  }
  //for (size_t i = 0; i < point_count; ++i) {
  //  const auto& cmd = point_data[i];
  //  switch (cmd.command) {
  //    case PathCommand::MOVE_TO:
  //      cairo_move_to(ctx, cmd[0], cmd[1]);
  //      break;
  //    case PathCommand::LINE_TO:
  //      cairo_line_to(ctx, cmd[0], cmd[1]);
  //      break;
  //  }
  //}

  cairo_stroke(ctx);
  //cairo_stroke(ctx);
}

void strokeLine(
+1 −1
Original line number Diff line number Diff line
@@ -23,7 +23,7 @@ Layer::Layer(
    dpi(dpi_),
    pixmap(PixelFormat::RGBA8, w, h),
    text_shaper(dpi),
    rasterizer(width, height, dpi) {}
    rasterizer(&pixmap, dpi) {}

Layer::~Layer() {}

+29 −26
Original line number Diff line number Diff line
@@ -8,26 +8,25 @@
 * <http://www.gnu.org/licenses/>.
 */
#include <signaltk/core/rasterize.h>
#include <signaltk/core/image.h>

namespace signaltk {

Rasterizer::Rasterizer(
    double width,
    double height,
    Image* pixmap_,
    double dpi_) :
    pixmap(pixmap_),
    dpi(dpi_),
    ft_ready(false) {
  surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
  ctx = cairo_create(surface);
  if (!FT_Init_FreeType(&ft)) {
    ft_ready = true;
  }
}

Rasterizer::~Rasterizer() {
  if (ft_ready) {
    FT_Done_FreeType(ft);
  }

  cairo_destroy(ctx);
  cairo_surface_destroy(surface);
}

Status Rasterizer::drawTextGlyphs(
@@ -35,13 +34,9 @@ Status Rasterizer::drawTextGlyphs(
    const GlyphPlacement* glyphs,
    size_t glyph_count) {
  if (!ft_ready) {
    if (FT_Init_FreeType(&ft)) {
    return ERROR;
  }

    ft_ready = true;
  }

  // FIXME cache
  FT_Face ft_font;
  if (FT_New_Face(ft, font_info.font_file.c_str(), 0, &ft_font)) {
@@ -53,24 +48,32 @@ Status Rasterizer::drawTextGlyphs(
    return ERROR;
  }

  auto cairo_font = cairo_ft_font_face_create_for_ft_face(ft_font, 0);
  auto cairo_glyphs = cairo_glyph_allocate(glyph_count);

  for (int i = 0; i < glyph_count; ++i) {
    printf("render glyph @ %f, %f\n", glyphs[i].x, glyphs[i].y);
    cairo_glyphs[i].index = glyphs[i].codepoint;
    cairo_glyphs[i].x = glyphs[i].x;
    cairo_glyphs[i].y = glyphs[i].y;
    const auto& g = glyphs[i];

    // FIXME also cache this
    FT_Load_Glyph(ft_font, g.codepoint, FT_LOAD_DEFAULT);
    FT_Render_Glyph(ft_font->glyph, FT_RENDER_MODE_NORMAL);

    const auto& ft_bitmap = ft_font->glyph->bitmap;
    for (uint32_t y = 0; y < ft_bitmap.rows; ++y) {
      for (uint32_t x = 0; x < ft_bitmap.width; ++x) {
        auto v = 1.0 - (ft_bitmap.buffer[y * ft_bitmap.width + x] / 255.0);

        auto ox = x + g.x + ft_font->glyph->bitmap_left;
        auto oy = y + g.y - ft_font->glyph->bitmap_top;

        if (ox >= pixmap->getWidth() || oy >= pixmap->getHeight()) {
          continue;
        }

  cairo_set_source_rgba(ctx, 0, 0, 0, 1.0);
  cairo_set_font_face(ctx, cairo_font);
  cairo_set_font_size(ctx, font_info.font_size);
  cairo_show_glyphs(ctx, cairo_glyphs, glyph_count);
        // FIXME alpha blend instead
        pixmap->setPixel(ox, oy, Colour::fromRGBA(v, v, v, 1));
      }
    }
  }

  cairo_glyph_free(cairo_glyphs);
  FT_Done_Face(ft_font);

  return OK;
}

+3 −3
Original line number Diff line number Diff line
@@ -27,11 +27,12 @@
#include <signaltk/core/text.h>

namespace signaltk {
class Image;

class Rasterizer {
public:

  Rasterizer(double width, double height, double dpi);
  Rasterizer(Image* pixmap, double dpi);
  ~Rasterizer();
  Rasterizer(const Rasterizer&) = delete;
  Rasterizer& operator=(const Rasterizer&) = delete;
@@ -42,8 +43,7 @@ public:
      size_t glyph_count);

  double dpi;
  cairo_surface_t* surface;
  cairo_t* ctx;
  Image* pixmap;
  FT_Library ft;
  bool ft_ready;
};
+2 −5
Original line number Diff line number Diff line
@@ -26,12 +26,9 @@ Status drawText(
    double x,
    double y,
    Layer* layer) {
  auto ctx = layer->rasterizer.ctx;
  auto dpi = layer->dpi;

  FontInfo font_info {
    .font_file = "/Library/Fonts/Arial.ttf",
    .font_size = 16
    .font_file = "/usr/share/fonts/google-roboto/Roboto-Regular.ttf",
    .font_size = 12
  };

  std::vector<GlyphPlacement> glyphs;