代码
#include <iostream>
#include "include/blend2d.h"
#include "include/blend2d/image.h"
void useCoreDrawImage() {
BLResult r;
BLImageCore img;
BLContextCore ctx;
r = blImageInitAs(&img, 480, 480, BL_FORMAT_PRGB32);
if (r != BL_SUCCESS)
return;
r = blContextInitAs(&ctx, &img, NULL);
if (r != BL_SUCCESS) {
// Image has been already created, so destroy it.
blImageDestroy(&img);
return;
}
blContextClearAll(&ctx);
// First shape filled with a radial gradient.
// By default, SRC_OVER composition is used.
BLGradientCore radial;
BLRadialGradientValues radialValues = {
180, 180, 180, 180, 180
};
blGradientInitAs(&radial,
BL_GRADIENT_TYPE_RADIAL, &radialValues,
BL_EXTEND_MODE_PAD, NULL, 0, NULL);
blGradientAddStopRgba32(&radial, 0.0, 0xFFFFFFFFu);
blGradientAddStopRgba32(&radial, 1.0, 0xFFFF6F3Fu);
BLCircle circle = {180, 180, 160};
blContextFillGeometryExt(&ctx,
BL_GEOMETRY_TYPE_CIRCLE, &circle, &radial);
// Unused styles must be destroyed.
blGradientDestroy(&radial);
// Second shape filled with a linear gradient.
BLGradientCore linear;
BLLinearGradientValues linearValues = {
195, 195, 470, 470
};
blGradientInitAs(&linear,
BL_GRADIENT_TYPE_LINEAR, &linearValues,
BL_EXTEND_MODE_PAD, NULL, 0, NULL);
blGradientAddStopRgba32(&linear, 0.0, 0xFFFFFFFFu);
blGradientAddStopRgba32(&linear, 1.0, 0xFF3F9FFFu);
// Use 'blContextSetCompOp()' to change a composition operator.
blContextSetCompOp(&ctx, BL_COMP_OP_DIFFERENCE);
BLRoundRect roundRect = { 195, 195, 270, 270, 25, 25 };
blContextFillGeometryExt(&ctx,
BL_GEOMETRY_TYPE_ROUND_RECT, &roundRect, &linear);
// Unused styles must be destroyed.
blGradientDestroy(&linear);
// Finalize the rendering and destroy the rendering context.
blContextDestroy(&ctx);
// An example of querying a codec from Blend2D internal codecs.
BLImageCodecCore codec;
blImageCodecInitByName(&codec, "PNG", SIZE_MAX, NULL);
blImageWriteToFile(&img, "bl_sample_capi.png", &codec);
blImageCodecDestroy(&codec);
blImageDestroy(&img);
}
void drawImage(int w, int h) {
BLImage m_blImage(w, h, BL_FORMAT_PRGB32);
BLContextCreateInfo createInfo{};
// GetPitch这个很重要了,图像的间距
// m_blImage.createFromData(m_bckImge.GetWidth(), m_bckImge.GetHeight(), BL_FORMAT_XRGB32, m_bckImge.GetBits(), m_bckImge.GetPitch());
BLContext ctx(m_blImage, createInfo);
ctx.setFillStyle(BLRgba32(0xFF000000));
ctx.fillAll();
BLPath path;
BLGradient linear(BLLinearGradientValues(0, 0, 0, 480));
// Color stops can be added in any order.
linear.addStop(0.0, BLRgba32(0xFFFFFFFF));
linear.addStop(0.5, BLRgba32(0xFF5FAFDF));
linear.addStop(1.0, BLRgba32(0xFF2F5FDF));
// `setFillStyle()` can be used for both colors
// and styles. Alternatively, a color or style
// can be passed explicitly to a render function.
ctx.setFillStyle(linear);
// Rounded rect will be filled with the linear
// gradient.
ctx.fillRoundRect(640.0, 40.0, 400.0, 400.0, 45.5);
int yLen = m_blImage.height();
int xLen = m_blImage.width();
int xCenter = m_blImage.width() / 2;
int yCenter = m_blImage.height() / 2;
path.addLine(BLLine(0, yCenter, xLen, yCenter));
path.addLine(BLLine(xCenter, 0, xCenter, yLen));
// 圆
path.addCircle(BLCircle(xCenter / 2, xCenter / 2, 50));
// 弧
path.addArc(BLArc(150, 150, 50, 50, 0, 120 * 3.1415926 / 180.0f));
// Create a path having cubic curves.
path.moveTo(26, 31);
path.cubicTo(642, 132, 587, -136, 25, 464);
path.cubicTo(882, 404, 144, 267, 27, 31);
BLFontFace face;
BLResult err = face.createFromFile("ABeeZee-Regular.ttf");
// 文字
BLFont font;
font.createFromFace(face, 50.0f);
ctx.setFillStyle(BLRgba32(0xFFFFFFFF));
ctx.fillUtf8Text(BLPoint(xCenter + 150, yCenter + 180), font, "Hello World!");
ctx.rotate(0.785398);
ctx.fillUtf8Text(BLPoint(250, 80), font, "rotatedText");
ctx.setCompOp(BL_COMP_OP_SRC_OVER);
ctx.setStrokeStyle(linear);
ctx.setStrokeWidth(1);
ctx.strokePath(path);
// Fill a path with opaque white - 0xAARRGGBB.
// ctx.fillPath(path, BLRgba32(0xFFFFFFFF));
ctx.end();
// Let's use some built-in codecs provided by Blend2D.
m_blImage.writeToFile("bl_sample_1.png");
}
void clipImage(int w, int h) {
BLImage img(w, h, BL_FORMAT_PRGB32);
BLContext ctx(img);
ctx.clearAll();
// Read an image from file.
BLImage texture;
BLResult err = texture.readFromFile("bl_sample_1.png");
// Handle a possible error.
if (err != BL_SUCCESS) {
printf("Failed to load a texture (err=%u)\n", err);
return;
}
// Rotate by 45 degrees about a point at [240, 240].
// ctx.rotate(0.785398, 240.0, 240.0);
// Create a pattern and use it to fill a rounded-rect.
// By default a repeat extend mode is used, but it can
// be configured to use more extend modes
BLPattern pattern(texture);
ctx.fillRoundRect(
BLRoundRect(640.0, 40.0, 400.0, 400.0, 45.5),
pattern);
ctx.end();
img.writeToFile("bl_sample_2.png");
}
void blendMode() {
BLImage img(480, 480, BL_FORMAT_PRGB32);
BLContext ctx(img);
ctx.clearAll();
// First shape filled with a radial gradient.
// By default, SRC_OVER composition is used.
BLGradient radial(
BLRadialGradientValues(180, 180, 180, 180, 180));
radial.addStop(0.0, BLRgba32(0xFFFFFFFF));
radial.addStop(1.0, BLRgba32(0xFFFF6F3F));
ctx.fillCircle(180, 180, 160, radial);
// Second shape filled with a linear gradient.
BLGradient linear(
BLLinearGradientValues(195, 195, 470, 470));
linear.addStop(0.0, BLRgba32(0xFFFFFFFF));
linear.addStop(1.0, BLRgba32(0xFF3F9FFF));
// Use 'setCompOp()' to change a composition operator.
ctx.setCompOp(BL_COMP_OP_DIFFERENCE);
ctx.fillRoundRect(
BLRoundRect(195, 195, 270, 270, 25), linear);
ctx.end();
img.writeToFile("blend.png");
}
int strokeCap() {
BLImage img(480, 480, BL_FORMAT_PRGB32);
BLContext ctx(img);
ctx.clearAll();
BLGradient linear(
BLLinearGradientValues(0, 0, 0, 480));
linear.addStop(0.0, BLRgba32(0xFFFFFFFF));
linear.addStop(0.5, BLRgba32(0xFFFF1F7F));
linear.addStop(1.0, BLRgba32(0xFF1F7FFF));
BLPath path;
path.moveTo(119, 49);
path.cubicTo(259, 29, 99, 279, 275, 267);
path.cubicTo(537, 245, 300, -170, 274, 430);
// Use 'setStrokeXXX' to change stroke options.
ctx.setStrokeWidth(15);
ctx.setStrokeStartCap(BL_STROKE_CAP_ROUND);
ctx.setStrokeEndCap(BL_STROKE_CAP_BUTT);
ctx.strokePath(path, linear);
ctx.end();
img.writeToFile("strokeCap.png");
return 0;
}
void multiLineText() {
BLImage img(480, 480, BL_FORMAT_PRGB32);
BLContext ctx(img);
const char fontName[] = "ABeeZee-Regular.ttf";
const char* str =
"Hello Blend2D!\n"
"I'm a simple multiline text example\n"
"that uses GlyphBuffer and GlyphRun!";
BLRgba32 color(0xFFFFFFFFu);
BLFontFace face;
BLResult result = face.createFromFile(fontName);
if (result != BL_SUCCESS) {
printf("Failed to load a face (err=%u)\n", result);
return;
}
BLFont font;
font.createFromFace(face, 20.0f);
BLGlyphBuffer gb;
BLTextMetrics tm;
BLFontMetrics fm = font.metrics();
double y = 190 + fm.ascent;
ctx.clearAll();
do {
const char* nl = strchr(str, '\n');
gb.setUtf8Text(str,
nl ? (size_t)(nl - str) : SIZE_MAX);
font.shape(gb);
font.getTextMetrics(gb, tm);
double x = (tm.boundingBox.x1 - tm.boundingBox.x0);
ctx.fillGlyphRun(BLPoint((480.0 - x) / 2, y),
font, gb.glyphRun(), color);
y += fm.ascent + fm.descent + fm.lineGap;
str = nl ? nl + 1 : nullptr;
} while (str);
ctx.end();
img.writeToFile("multi_line_text.png");
}
int main() {
drawImage(1600, 900); // 绘制
clipImage(1600, 900); // 裁剪
blendMode(); // 混合模式
strokeCap(); // 描边
multiLineText(); // 多行文本排版
printf("Hello World!");
return 0;
}
效果
参考
https://github.com/blend2d/blend2d