Commit 6b5053ea authored by Paul Asmuth's avatar Paul Asmuth
Browse files

implement custom default font selection

parent d93be1c5
Loading
Loading
Loading
Loading
+26 −2
Original line number Diff line number Diff line
@@ -33,10 +33,22 @@ Environment::Environment() :
    font_size(from_pt(11, dpi)) {}

ReturnCode environment_setup_defaults(Environment* env) {
  if (!font_load(DefaultFont::HELVETICA_REGULAR, &env->font)) {
  if (!font_load(DefaultFont::ROMAN_SANS_MEDIUM, &env->font)) {
    return error(
        ERROR,
        "unable to find default sans-sans font (Helvetica/Arial)");
        "unable to find default roman sans font (Helvetica/Arial)");
  }

  if (!font_load(DefaultFont::ROMAN_SANS_BOLD, &env->font_em)) {
    return error(
        ERROR,
        "unable to find default roman sans font (Helvetica/Arial)");
  }

  if (!font_load(DefaultFont::ROMAN_SANS_REGULAR, &env->font_symbol)) {
    return error(
        ERROR,
        "unable to find default roman sans font (Helvetica/Arial)");
  }

  return OK;
@@ -60,6 +72,18 @@ ReturnCode environment_set(Environment* env, const Expr* expr) {
    return expr_to_float64(args[1], &env->dpi);
  }

  if (expr_is_value(args[0], "font")) {
    return font_configure(args[1], &env->font);
  }

  if (expr_is_value(args[0], "font-emphasis")) {
    return font_configure(args[1], &env->font_em);
  }

  if (expr_is_value(args[0], "font-symbols")) {
    return font_configure(args[1], &env->font_symbol);
  }

  if (expr_is_value(args[0], "font-size")) {
    return expr_to_measure(args[1], &env->font_size);
  }
+2 −0
Original line number Diff line number Diff line
@@ -30,6 +30,8 @@ struct Environment {
  Measure screen_height;
  double dpi;
  FontInfo font;
  FontInfo font_em;
  FontInfo font_symbol;
  Measure font_size;
  ColorScheme color_scheme;
  Color background_color;
+124 −12
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include <iostream>
#include <fontconfig/fontconfig.h>
#include "font_lookup.h"
#include "sexpr.h"
#include "utils/fileutil.h"

namespace fviz {
@@ -51,31 +52,46 @@ bool findFontSystem(
}

ReturnCode font_load(DefaultFont font_name, FontInfo* font_info) {
  std::string font_css;
  std::string font_fc;

  switch (font_name) {
    default:
    case SANS_REGULAR:
    case HELVETICA_REGULAR:
      font_css = "Arial,Helvetica,'Helvetica Neue',sans-serif";
    case ROMAN_SANS_REGULAR:
      font_fc = "Arial,Helvetica,Helvetica Neue:style=Regular,Roman";
      font_info->font_family_css = "Arial,Helvetica,'Helvetica Neue',sans-serif";
      font_info->font_weight_css = 400;
      break;

    case SANS_MEDIUM:
    case HELVETICA_MEDIUM:
      font_css = "Arial,Helvetica,'Helvetica Neue',sans-serif";
    case ROMAN_SANS_MEDIUM:
      font_fc = "Arial,Helvetica,Helvetica Neue:style=Medium,Roman";
      font_info->font_family_css = "Arial,Helvetica,'Helvetica Neue',sans-serif";
      font_info->font_weight_css = 500;
      break;

    case SANS_BOLD:
    case HELVETICA_BOLD:
      font_css = "Arial,Helvetica,'Helvetica Neue',sans-serif";
    case ROMAN_SANS_BOLD:
      font_fc = "Arial,Helvetica,Helvetica Neue:style=Bold,Roman";
      font_info->font_family_css = "Arial,Helvetica,'Helvetica Neue',sans-serif";
      font_info->font_weight_css = 600;
      break;
  }

  font_info->font_family_css = font_css;
    case ROMAN_SERIF_REGULAR:
      font_fc = "CMU Serif,serif:style=Regular,Roman";
      font_info->font_family_css = "'CMU Serif', serif";
      font_info->font_weight_css = 400;
      break;

    case ROMAN_SERIF_MEDIUM:
      font_fc = "CMU Serif,serif:style=Regular,Roman";
      font_info->font_family_css = "'CMU Serif', serif";
      font_info->font_weight_css = 500;
      break;

    case ROMAN_SERIF_BOLD:
      font_fc = "CMU Serif,serif:style=Regular,Roman";
      font_info->font_family_css = "'CMU Serif', serif";
      font_info->font_weight_css = 600;
      break;
  }

  if (!findFontSystem(font_fc, &font_info->font_file)) {
    return ERROR;
@@ -84,5 +100,101 @@ ReturnCode font_load(DefaultFont font_name, FontInfo* font_info) {
  return OK;
}

ReturnCode font_configure(const Expr* expr, FontInfo* font_info) {
  if (expr_is_value(expr, "roman-sans") ||
      expr_is_value(expr, "roman-sans-regular")) {
    return font_load(ROMAN_SANS_REGULAR, font_info);
  }

  if (expr_is_value(expr, "roman-sans-medium")) {
    return font_load(ROMAN_SANS_MEDIUM, font_info);
  }

  if (expr_is_value(expr, "roman-sans-bold")) {
    return font_load(ROMAN_SANS_BOLD, font_info);
  }

  if (expr_is_value(expr, "roman-serif") ||
      expr_is_value(expr, "roman-serif-regular")) {
    return font_load(ROMAN_SERIF_REGULAR, font_info);
  }

  if (expr_is_value(expr, "roman-serif-medium")) {
    return font_load(ROMAN_SERIF_MEDIUM, font_info);
  }

  if (expr_is_value(expr, "roman-serif-bold")) {
    return font_load(ROMAN_SERIF_BOLD, font_info);
  }

  std::vector<std::string> font_names;
  std::string font_fc;
  std::string font_style_fc;
  std::string font_css;
  double font_style_css = 400;
  for (auto arg = expr; arg; arg = expr_next(arg)) {
    if (!expr_is_value(arg)) {
      return errorf(
          ERROR,
          "argument error; expected a value, got: {}",
          expr_inspect(expr));
    }

    auto font_name = expr_get_value(arg);
    if (font_name == "Regular" || font_name == "regular") {
      font_style_css = 400;
      font_style_fc = "Regular";
      continue;
    }

    if (font_name == "Medium" || font_name == "medium" ||
        font_name == "Semibold" || font_name == "semibold" ||
        font_name == "Demibold" || font_name == "demibold") {
      font_style_css = 500;
      font_style_fc = "Medium";
      continue;
    }

    if (font_name == "Bold" || font_name == "bold") {
      font_style_css = 600;
      font_style_fc = "Bold";
      continue;
    }

    if (font_name == "Thin" || font_name == "thin" ||
        font_name == "Light" || font_name == "light") {
      font_style_css = 300;
      font_style_fc = "Light";
      continue;
    }

    font_names.emplace_back(font_name);

    if (!font_fc.empty()) {
      font_fc += ",";
    }

    font_fc += font_name;

    if (!font_css.empty()) {
      font_css += ",";
    }

    font_css += "'" + font_name + "'"; // FIXME
  }

  if (!font_style_fc.empty()) {
    font_fc += ":style=" + font_style_fc;
  }

  if (!findFontSystem(font_fc, &font_info->font_file)) {
    return errorf(ERROR, "unble to find font: {}", expr_inspect(expr));
  }

  font_info->font_family_css = font_css;
  font_info->font_weight_css = font_style_css;
  return OK;
}

} // namespace fviz
+8 −6
Original line number Diff line number Diff line
@@ -22,15 +22,17 @@ bool findFontSystem(
    std::string* font_file);

enum DefaultFont {
  SANS_REGULAR,
  SANS_MEDIUM,
  SANS_BOLD,
  HELVETICA_REGULAR,
  HELVETICA_MEDIUM,
  HELVETICA_BOLD,
  ROMAN_SANS_REGULAR,
  ROMAN_SANS_MEDIUM,
  ROMAN_SANS_BOLD,
  ROMAN_SERIF_REGULAR,
  ROMAN_SERIF_MEDIUM,
  ROMAN_SERIF_BOLD,
};

ReturnCode font_load(DefaultFont font_name, FontInfo* font_info);

ReturnCode font_configure(const Expr* expr, FontInfo* font_info);

} // namespace fviz
+1 −0
Original line number Diff line number Diff line
@@ -96,6 +96,7 @@ Status svg_text_span(
    << svg_attr("fill", style.color.to_hex_str())
    << svg_attr("font-size", style.font_size)
    << svg_attr("font-family", style.font.font_family_css)
    << svg_attr("font-weight", style.font.font_weight_css)
    << transform
    << ">"
    << svg_body(op.text)
Loading