Commit 4f60d18a authored by Paul Asmuth's avatar Paul Asmuth
Browse files

move cairo bindings into core/rasterize.{h,cc}

parent 0811b65b
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ add_library(signaltk STATIC
    src/signaltk/core/layer.cc
    src/signaltk/core/text.cc
    src/signaltk/core/image_api.cc
    src/signaltk/core/rasterize.cc
    src/signaltk/plot/gridlines.cc
    src/signaltk/plot/axes.cc
    src/signaltk/plot/domain.cc
+1 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@ void strokePath(
    const PathData* point_data,
    size_t point_count,
    const StrokeStyle& style) {
  auto ctx = layer->ctx;
  auto ctx = layer->rasterizer.ctx;

  if (point_count < 2) {
    return;
+28 −29
Original line number Diff line number Diff line
@@ -12,51 +12,50 @@

namespace signaltk {

Layer::Layer() : width(0), height(0), surface(nullptr), ctx(nullptr) {}

Layer::Layer(
    uint32_t w,
    uint32_t h,
    uint32_t dpi_ /* = 300 */) :
    width(w),
    height(h),
    dpi(dpi_) {
  surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
  ctx = cairo_create(surface);
}
    dpi(dpi_),
    text_shaper(dpi),
    rasterizer(width, height, dpi) {}

Layer::~Layer() {
  cairo_destroy(ctx);
  cairo_surface_destroy(surface);
}
Layer::~Layer() {}

void Layer::clear(const Colour& c) {
  auto ctx = rasterizer.ctx;
  cairo_set_source_rgba(ctx, c.red(), c.green(), c.blue(), c.alpha());
  cairo_rectangle(ctx, 0, 0, width, height);
  cairo_fill(ctx);
}

bool Layer::loadPNG(const char* path) {
  if (surface || ctx) {
    return false;
  }

  surface = cairo_image_surface_create_from_png(path);
  if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
    return false;
  }

  ctx = cairo_create(surface);

  double extent[4];
  cairo_clip_extents(ctx, extent + 0, extent + 1, extent + 2, extent + 3);
  width = extent[2] - extent[0];
  height = extent[3] - extent[1];

  return true;
}
//bool Layer::loadPNG(const char* path) {
//  auto surface = rasterizer.surface;
//  auto ctx = rasterizer.ctx;
//  if (surface || ctx) {
//    return false;
//  }
//
//  surface = cairo_image_surface_create_from_png(path);
//  if (cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
//    return false;
//  }
//
//  ctx = cairo_create(surface);
//
//  double extent[4];
//  cairo_clip_extents(ctx, extent + 0, extent + 1, extent + 2, extent + 3);
//  width = extent[2] - extent[0];
//  height = extent[3] - extent[1];
//
//  return true;
//}

bool Layer::writePNG(const char* path) const {
  auto surface = rasterizer.surface;
  auto ctx = rasterizer.ctx;
  if (!surface || !ctx) {
    return false;
  }
+3 −3
Original line number Diff line number Diff line
@@ -12,8 +12,9 @@
#include <stdlib.h>
#include <vector>
#include <string>
#include <cairo.h>

#include "colour.h"
#include <signaltk/core/rasterize.h>

namespace signaltk {

@@ -33,8 +34,7 @@ struct Layer {
  uint32_t width;
  uint32_t height;
  uint32_t dpi;
  cairo_surface_t* surface;
  cairo_t* ctx;
  Rasterizer rasterizer;
};

} // namespace signaltk
+77 −0
Original line number Diff line number Diff line
/**
 * This file is part of the "signaltk" project
 *   Copyright (c) 2018 Paul Asmuth
 *
 * libstx is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License v3.0. You should have received a
 * copy of the GNU General Public License along with this program. If not, see
 * <http://www.gnu.org/licenses/>.
 */
#include <signaltk/core/rasterize.h>

namespace signaltk {

Rasterizer::Rasterizer(
    double width,
    double height,
    double dpi_) :
    dpi(dpi_),
    ft_ready(false) {
  surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
  ctx = cairo_create(surface);
}

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

  cairo_destroy(ctx);
  cairo_surface_destroy(surface);
}

Status Rasterizer::drawTextGlyphs(
    const FontInfo& font_info,
    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)) {
    return ERROR;
  }

  if (FT_Set_Char_Size(ft_font, 0, font_info.font_size * 64, dpi, dpi)) {
    FT_Done_Face(ft_font);
    return ERROR;
  }

  auto cairo_font = cairo_ft_font_face_create_for_ft_face(ft_font, 0);
  auto cairo_glyphs = static_cast<cairo_glyph_t*>(malloc(sizeof(cairo_glyph_t) * glyph_count));

  for (int i = 0; i < glyph_count; ++i) {
    cairo_glyphs[i].index = glyphs[i].codepoint;
    cairo_glyphs[i].x = glyphs[i].x;
    cairo_glyphs[i].y = glyphs[i].y;
  }

  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);

  free(cairo_glyphs);
  FT_Done_Face(ft_font);

  return OK;
}

} // namespace signaltk
Loading