Blend2D development is currently on hold due to insufficient funding. For more information, please see the Funding Page.

Switching to {snake_case}

Since AsmJit has moved to use snake_case naming convention for function names and variables it was a great opportunity to convert Blend2D source code too. Originally, both AsmJit & Blend2D used camelCase naming convention for variables and member function names. However, this has been later seen as a mistake in the API design. There was a lot of places in AsmJit that always used snake_case so converting the whole code-base made a lot of sense for consistency.

In general, low-level functionality often requires prefixing functions or using very short words - for example when gp or k are combined with other words in a camelCased way the combination such as newGp() or newK() doesn't look very nice. There is a much better looking alternative - new_gp() and new_k(). It's not just this - deciding between newMm() and newMM in case of camelCase convention was always painful as no variation looked well. We can probably continue and start considering hasAvx512F() or hasAvxNeConvert(), and so on...

In Blend2D API there are often uses of one-letter variables like x and y and sometimes the variables or struct members have these as part of their full names, which again creates interesting names such as xOrigin or yBand, etc... With snake_case this is no longer a problem and the previous two would become x_origin and y_band, which is much more consistent and readable.

Conversion Process

I haven't found a reliable tool to do the conversion automatically especially when you have to deal with documentation, external resources, and multiple variations of a snake_cased name. So, what I have done was to use a regex and to confirm many replacements manually. Since both AsmJit and Blend2D have no dependencies I didn't have to deal with API of dependencies, only with system API, which is usually snake_case anyway. I have done 90% of work the first day with a little focus, and then the remaining 10% when I had free time and focus.

The regex based solution was great as it also covered comments, external documentation, and websites, which had to be updated too. In general this is a place where many projects get out of sync quickly - source code changes, but not the documentation, so after years of improvements the documentation suggests invalid examples. It would be best to have an extraction tool that would try to compile all snippets to make sure they are working, but that's something I don't have time budget for.

API Examples

The examples below show the naming difference of the first snippet shown on the Blend2D homepage:

Old API

#include <blend2d.h>

void render(BLImage& img) noexcept {
  BLContext ctx;
  BLGradient gradient;

  if (img.create(256, 256, BL_FORMAT_PRGB32) != BL_SUCCESS)
    return;

  if (ctx.begin(img) != BL_SUCCESS)
    return;

  gradient.create(
    BLLinearGradientValues(0, 0, 256, 256),
    BL_EXTEND_MODE_PAD /* default if omitted */);

  gradient.addStop(0.0, BLRgba32(0x00000000));
  gradient.addStop(1.0, BLRgba32(0xFFFFFFFF));

  ctx.setCompOp(BL_COMP_OP_SRC_COPY);
  ctx.fillAll(gradient);
  ctx.end();
}

New API

#include <blend2d.h>

void render(BLImage& img) noexcept {
  BLContext ctx;
  BLGradient gradient;

  if (img.create(256, 256, BL_FORMAT_PRGB32) != BL_SUCCESS)
    return;

  if (ctx.begin(img) != BL_SUCCESS)
    return;

  gradient.create(
    BLLinearGradientValues(0, 0, 256, 256),
    BL_EXTEND_MODE_PAD /* default if omitted */);

  gradient.add_stop(0.0, BLRgba32(0x00000000));
  gradient.add_stop(1.0, BLRgba32(0xFFFFFFFF));

  ctx.set_comp_op(BL_COMP_OP_SRC_COPY);
  ctx.fill_all(gradient);
  ctx.end();
}

The changes are not really dramatic when it comes to the API, but it's a breaking change of course.

Other Changes

Most of the changes were about the coding style, but in AsmJit case I have done quite more as I wanted to consolidate my local changes as well (to prevent renaming things twice). This includes register allocation improvements - now AsmJit contains an optimized liveness analysis that understands basic-block locals and would only perform liveness analysis of virtual registers that span across multiple basic-blocks. This optimizes almost all cases.

There are minor changes also to both AsmJit and Blend2D websites, which now use more unified CSS (the core is shared between the sites), so the sites look very similar now, which means much less maintenance on my side. Doxygen-deuglifier (a tool I wrote to process the doxygen generated docs) got a little bit bigger and does more transformations as well.

Conclusion

I understand that for many people breaking changes are pain, but this was something I wanted to do many years ago, but I have never done it for this exact reason. Since it didn't take me that much time to do it, I believe for many users this would be a question of few minutes as well.