UE4在蓝图里面是没有2D绘图引擎的(或者我没找到),所以需要另外找一个第三方的2D引擎。
Skia和Cairo都用了一下。Cairo是C接口,里面很多参数得实验才知道怎么用,很多功能的封装必须多个函数搭配使用才能完成,用起来颇为蛋疼,试了几天就放弃了。Skia使用C++,有Bitmap,Paint,Canvas,Path的等概念,OOP的思想和UE4接口封装适配的很好。试了几天,终于封装了Skia的部分接口.
尽量保持了UE4和Skia在接口上的一致性,自己还是颇为满意的。
基本图形
Snipaste_2019-02-20_17-47-29.png
正旋曲线,和螺旋曲线
Snipaste_2019-02-20_17-43-56.png
SkiaBPLibrary.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "Kismet/BlueprintFunctionLibrary.h"
#include "Runtime/Core/Public/Math/Color.h"
#include "Runtime/Engine/Classes/Engine/Texture2D.h"
#include <memory>
#include "SkiaBPLibrary.generated.h"
class SkBitmap;
class SkCanvas;
class SkPaint;
class SkPath;
#pragma region Struct
USTRUCT(BlueprintType, Blueprintable)
struct FSkiaBitmap
{
GENERATED_USTRUCT_BODY()
std::shared_ptr<SkBitmap> bitmap = nullptr;
UPROPERTY(BlueprintReadOnly)
float imageWidth = 0.0;
UPROPERTY(BlueprintReadOnly)
float imageHeight = 0.0;
};
USTRUCT(BlueprintType, Blueprintable)
struct FSkiaCanvas
{
GENERATED_USTRUCT_BODY()
std::shared_ptr<SkCanvas> canvas = nullptr;
};
USTRUCT(BlueprintType, Blueprintable)
struct FSkiaPaint
{
GENERATED_USTRUCT_BODY()
std::shared_ptr<SkPaint> paint = nullptr;
};
USTRUCT(BlueprintType, Blueprintable)
struct FSkiaContext
{
GENERATED_USTRUCT_BODY()
UPROPERTY(BlueprintReadOnly)
FSkiaBitmap bitmap;
UPROPERTY(BlueprintReadOnly)
FSkiaCanvas canvas;
UPROPERTY(BlueprintReadOnly)
UTexture2D* texture = nullptr;
std::shared_ptr<FUpdateTextureRegion2D> region = nullptr;
std::shared_ptr<TArray<FColor>> data;
UPROPERTY(BlueprintReadOnly)
float imageWidth = 0.0;
UPROPERTY(BlueprintReadOnly)
float imageHeight = 0.0;
};
USTRUCT(BlueprintType, Blueprintable)
struct FSkiaPath
{
GENERATED_USTRUCT_BODY()
std::shared_ptr<SkPath> path = nullptr;
};
USTRUCT(BlueprintType, Blueprintable)
struct FSkiaGradient
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Skia")
float offset;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Skia")
FLinearColor color;
};
USTRUCT(BlueprintType, Blueprintable)
struct FSkiaLine
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Skia")
FVector2D p0;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Skia")
FVector2D p1;
};
USTRUCT(BlueprintType, Blueprintable)
struct FSkiaRect
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Skia")
FVector2D point;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Skia")
FVector2D size;
};
USTRUCT(BlueprintType, Blueprintable)
struct FSkiaCircle
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Skia")
FVector2D center;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Skia")
float radius;
};
USTRUCT(BlueprintType, Blueprintable)
struct FSkiaArc
{
GENERATED_USTRUCT_BODY()
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Skia")
FVector2D point;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Skia")
FVector2D size;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Skia")
float startAngle;
UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Skia")
float sweepAngle;
};
#pragma endregion
#pragma region Enum
UENUM(BlueprintType)
enum class EPaintStyle :uint8
{
Paint_kFill_Style UMETA(DisplayName = "Fill"),
Paint_kStroke_Style UMETA(DisplayName = "Stroke"),
Paint_kStrokeAndFill_Style UMETA(DisplayName = "Stroke And Fill"),
};
UENUM(BlueprintType)
enum class ECanvasPointMode :uint8
{
Canvas_kPoints_PointMode UMETA(DisplayName = "Points"),
Canvas_kLines_PointMode UMETA(DisplayName = "Lines"),
Canvas_kPolygon_PointMode UMETA(DisplayName = "Polygon"),
};
UENUM(BlueprintType)
enum class EPaintAlign :uint8
{
Paint_kLeft_Align UMETA(DisplayName = "Left"),
Paint_kCenter_Align UMETA(DisplayName = "Center"),
Paint_kRight_Align UMETA(DisplayName = "Right"),
};
UENUM(BlueprintType)
enum class EPaintCap :uint8
{
Paint_kButt_Cap UMETA(DisplayName = "Butt"),
Paint_kRound_Cap UMETA(DisplayName = "Round"),
Paint_kSquare_Cap UMETA(DisplayName = "Square"),
Paint_kLast_Cap = Paint_kSquare_Cap UMETA(DisplayName = "Last"),
Paint_kDefault_Cap = Paint_kButt_Cap UMETA(DisplayName = "Default"),
};
UENUM(BlueprintType)
enum class EPaintJoin :uint8
{
Paint_kMiter_Join UMETA(DisplayName = "Miter"),
Paint_kRound_Join UMETA(DisplayName = "Round"),
Paint_kBevel_Join UMETA(DisplayName = "Bevel"),
Paint_kLast_Join = Paint_kBevel_Join UMETA(DisplayName = "Last"),
Paint_kDefault_Join = Paint_kMiter_Join UMETA(DisplayName = "Default"),
};
UENUM(BlueprintType)
enum class EPaintTileMode :uint8
{
Paint_kClamp_TileMode UMETA(DisplayName = "Clamp"),
Paint_kRepeat_TileMode UMETA(DisplayName = "Repeat"),
Paint_kMirror_TileMode UMETA(DisplayName = "Mirror"),
Paint_kDecal_TileMode UMETA(DisplayName = "Decal"),
Paint_kLast_TileMode = Paint_kDecal_TileMode UMETA(DisplayName = "Last")
};
UENUM(BlueprintType)
enum class EPathFillType :uint8
{
Path_kWinding_FillType UMETA(DisplayName = "Winding"),
Path_kEvenOdd_FillType UMETA(DisplayName = "EvenOdd"),
Path_kInverseWinding_FillType UMETA(DisplayName = "InverseWinding"),
Path_kInverseEvenOdd_FillType UMETA(DisplayName = "InverseEvenOdd"),
};
UENUM(BlueprintType)
enum class EFontType :uint8
{
Font_Normal UMETA(DisplayName = "Normal"),
Font_Bold UMETA(DisplayName = "Bold"),
Font_Italic UMETA(DisplayName = "Italic"),
Font_BoldItalic UMETA(DisplayName = "BoldItalic"),
};
UENUM(BlueprintType)
enum class EClipOp :uint8
{
ClipOp_kDifference UMETA(DisplayName = "Difference"),
ClipOp_kIntersect UMETA(DisplayName = "Intersect"),
ClipOp_kExtraEnumNeedInternallyPleaseIgnoreWillGoAway2 UMETA(DisplayName = "Ignore2"),
ClipOp_kExtraEnumNeedInternallyPleaseIgnoreWillGoAway3 UMETA(DisplayName = "Ignore3"),
ClipOp_kExtraEnumNeedInternallyPleaseIgnoreWillGoAway4 UMETA(DisplayName = "Ignore4"),
ClipOp_kExtraEnumNeedInternallyPleaseIgnoreWillGoAway5 UMETA(DisplayName = "Ignore5"),
ClipOp_kMax_EnumValue UMETA(DisplayName = "Max"),
};
UENUM(BlueprintType)
enum class ECanvasBlendMode :uint8
{
Canvas_kClear, //!< [0, 0]
Canvas_kSrc, //!< [Sa, Sc]
Canvas_kDst, //!< [Da, Dc]
Canvas_kSrcOver, //!< [Sa + Da * (1 - Sa), Sc + Dc * (1 - Sa)]
Canvas_kDstOver, //!< [Da + Sa * (1 - Da), Dc + Sc * (1 - Da)]
Canvas_kSrcIn, //!< [Sa * Da, Sc * Da]
Canvas_kDstIn, //!< [Da * Sa, Dc * Sa]
Canvas_kSrcOut, //!< [Sa * (1 - Da), Sc * (1 - Da)]
Canvas_kDstOut, //!< [Da * (1 - Sa), Dc * (1 - Sa)]
Canvas_kSrcATop, //!< [Da, Sc * Da + Dc * (1 - Sa)]
Canvas_kDstATop, //!< [Sa, Dc * Sa + Sc * (1 - Da)]
Canvas_kXor, //!< [Sa + Da - 2 * Sa * Da, Sc * (1 - Da) + Dc * (1 - Sa)]
Canvas_kPlus, //!< [Sa + Da, Sc + Dc]
Canvas_kModulate, // multiplies all components (= alpha and color)
Canvas_kScreen,
Canvas_kLastCoeffMode = Canvas_kScreen,
Canvas_kOverlay,
Canvas_kDarken,
Canvas_kLighten,
Canvas_kColorDodge,
Canvas_kColorBurn,
Canvas_kHardLight,
Canvas_kSoftLight,
Canvas_kDifference,
Canvas_kExclusion,
Canvas_kMultiply,
Canvas_kLastSeparableMode = Canvas_kMultiply,
Canvas_kHue,
Canvas_kSaturation,
Canvas_kColor,
Canvas_kLuminosity,
Canvas_kLastMode = Canvas_kLuminosity,
};
#pragma endregion
UCLASS()
class EXCHANGELIBRARY_API USkiaBPLibrary : public UBlueprintFunctionLibrary
{
GENERATED_UCLASS_BODY()
public:
UFUNCTION(BlueprintCallable, Category = "Skia")
static void CreateContext(float imageWidth, float imageHeight, FSkiaContext& context, FLinearColor color = FLinearColor::Transparent, bool createTexture = true);
UFUNCTION(BlueprintCallable, Category = "Skia")
static void UpdateTexture(const FSkiaContext& context);
//////////////////////////////////////Paint//////////////////////////////////////
UFUNCTION(BlueprintCallable, Category = "Skia|Paint")
static void CreatePaint(FSkiaPaint& paint);
UFUNCTION(BlueprintCallable, Category = "Skia|Paint")
static const FSkiaPaint& SetPaintStyle(const FSkiaPaint& paint, EPaintStyle style, EPaintCap cap = EPaintCap::Paint_kDefault_Cap, EPaintJoin join = EPaintJoin::Paint_kDefault_Join);
UFUNCTION(BlueprintCallable, Category = "Skia|Paint")
static const FSkiaPaint& SetPaintColor(const FSkiaPaint& paint, FLinearColor color);
UFUNCTION(BlueprintCallable, Category = "Skia|Paint")
static const FSkiaPaint& SetPaintStrokeWidth(const FSkiaPaint& paint, int width);
UFUNCTION(BlueprintCallable, Category = "Skia|Paint")
static const FSkiaPaint& SetPathEffect(const FSkiaPaint& paint, const TArray<float>& intervals, float phase);
UFUNCTION(BlueprintCallable, Category = "Skia|Paint|Text")
static const FSkiaPaint& SetTypeFace(const FSkiaPaint& paint, FString familyName, EFontType fontType = EFontType::Font_Normal);
UFUNCTION(BlueprintCallable, Category = "Skia|Paint|Text")
static const FSkiaPaint& SetPaintTextAlign(const FSkiaPaint& paint, EPaintAlign textAlign);
UFUNCTION(BlueprintCallable, Category = "Skia|Paint|Text")
static const FSkiaPaint& SetPaintTextSize(const FSkiaPaint& paint, float textSize);
UFUNCTION(BlueprintCallable, Category = "Skia|Paint|Text")
static const FSkiaPaint& SetPaintAntiAlias(const FSkiaPaint& paint, bool antiAlias);
UFUNCTION(BlueprintCallable, Category = "Skia|Paint|Text")
static const FSkiaPaint& SetPaintTextScaleX(const FSkiaPaint& paint, float scale);
UFUNCTION(BlueprintCallable, Category = "Skia|Paint|Text")
static const FSkiaPaint& SetPaintTextSkewX(const FSkiaPaint& paint, float skew);
UFUNCTION(BlueprintCallable, Category = "Skia|Paint|Text")
static const FSkiaPaint& MeasureText(const FSkiaPaint& paint, const FString& text, FSkiaRect& rect);
UFUNCTION(BlueprintCallable, Category = "Skia|Paint|Gradient")
static const FSkiaPaint& SetPaintGradientLiner(const FSkiaPaint& paint, FVector2D start, FVector2D end, TArray<FSkiaGradient> gradients, EPaintTileMode mode);
UFUNCTION(BlueprintCallable, Category = "Skia|Paint|Gradient")
static const FSkiaPaint& SetPaintGradientRadial(const FSkiaPaint& paint, FVector2D center, float radius, TArray<FSkiaGradient> gradients, EPaintTileMode mode);
UFUNCTION(BlueprintCallable, Category = "Skia|Paint|Gradient")
static const FSkiaPaint& SetPaintGradientSweep(const FSkiaPaint& paint, FVector2D center, TArray<FSkiaGradient> gradients);
//////////////////////////////////////Transfor//////////////////////////////////////
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas|Transfor")
static void Translate(const FSkiaCanvas& canvas, float dx, float dy);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas|Transfor")
static void Scale(const FSkiaCanvas& canvas, float sx, float sy);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas|Transfor")
static void Rotate(const FSkiaCanvas& canvas, float angle);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas|Transfor")
static void Rotate2(const FSkiaCanvas& canvas, float angle, float px, float py);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas|Transfor")
static void Skew(const FSkiaCanvas& canvas, float sx, float sy);
//////////////////////////////////////Canvas//////////////////////////////////////
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void DrawColor(const FSkiaCanvas& canvas, FLinearColor color, ECanvasBlendMode mode = ECanvasBlendMode::Canvas_kSrcOver);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void Clear(const FSkiaCanvas& canvas, FLinearColor color);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void DrawPaint(const FSkiaCanvas& canvas, const FSkiaPaint& paint);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void DrawPoint(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D point);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void DrawPoints(const FSkiaCanvas& canvas, const FSkiaPaint& paint, ECanvasPointMode mode, TArray<FVector2D> points);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void DrawLine(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D p0, FVector2D p1);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void DrawLine2(const FSkiaCanvas& canvas, const FSkiaPaint& paint, const FSkiaLine& line);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void DrawPolyline(const FSkiaCanvas& canvas, const FSkiaPaint& paint, TArray<FVector2D> points, bool closed = false);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void DrawRect(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D point, FVector2D size);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void DrawRect2(const FSkiaCanvas& canvas, const FSkiaPaint& paint, const FSkiaRect& rect);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void DrawRoundRect(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D point, FVector2D size, float rx, float ry);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void DrawArc(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D point, FVector2D size, float startAngle, float sweepAngle, bool useCenter);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void DrawArc2(const FSkiaCanvas& canvas, const FSkiaPaint& paint, const FSkiaArc& arc, bool useCenter);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void DrawOval(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D point, FVector2D size);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void DrawCircle(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D center, float radius);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void DrawCircle2(const FSkiaCanvas& canvas, const FSkiaPaint& paint, const FSkiaCircle& circle);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static FSkiaRect DrawText(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D point, FString text);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void ClipRect(const FSkiaCanvas& canvas, FVector2D point, FVector2D size, EClipOp op = EClipOp::ClipOp_kIntersect, bool doAntiAlias = false);
UFUNCTION(BlueprintCallable, Category = "Skia|Canvas")
static void ClipPath(const FSkiaCanvas& canvas, const FSkiaPath& path, EClipOp op = EClipOp::ClipOp_kIntersect, bool doAntiAlias = false);
UFUNCTION(BlueprintCallable, Category = "Skia|Bitmap")
static void CreateBitmap(FString filePath, FSkiaBitmap& bitmap);
UFUNCTION(BlueprintCallable, Category = "Skia|Bitmap")
static void DrawBitmap(const FSkiaCanvas& canvas, const FSkiaBitmap& bitmap, FVector2D point);
//////////////////////////////////////Path//////////////////////////////////////
UFUNCTION(BlueprintCallable, Category = "Skia|Path")
static void CreatePath(FSkiaPath& path);
UFUNCTION(BlueprintCallable, Category = "Skia|Path")
static void MoveTo(const FSkiaPath& path, FVector2D point);
UFUNCTION(BlueprintCallable, Category = "Skia|Path")
static void LineTo(const FSkiaPath& path, FVector2D point);
UFUNCTION(BlueprintCallable, Category = "Skia|Path")
static void QuadTo(const FSkiaPath& path, FVector2D pt1, FVector2D pt2);
UFUNCTION(BlueprintCallable, Category = "Skia|Path")
static void ConicTo(const FSkiaPath& path, FVector2D pt1, FVector2D pt2, float w);
UFUNCTION(BlueprintCallable, Category = "Skia|Path")
static void CubicTo(const FSkiaPath& path, FVector2D pt1, FVector2D pt2, FVector2D pt3);
UFUNCTION(BlueprintCallable, Category = "Skia|Path")
static void ArcTo(const FSkiaPath& path, FVector2D point, FVector2D size, float startAngle, float sweepAngle, bool forceMoveTo);
UFUNCTION(BlueprintCallable, Category = "Skia|Path")
static void ArcTo2(const FSkiaPath& path, FVector2D pt1, FVector2D pt2, float radius);
UFUNCTION(BlueprintCallable, Category = "Skia|Path")
static void DrawPath(const FSkiaCanvas& canvas, const FSkiaPaint& paint, const FSkiaPath& path, bool closed = false, EPathFillType fillType = EPathFillType::Path_kWinding_FillType);
//////////////////////////////////////Algorithm//////////////////////////////////////
};
SkiaBPLibrary.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "SkiaBPLibrary.h"
#include "Runtime/Engine/Classes/Engine/Texture2D.h"
#include "Runtime/Engine/Classes/Engine/TextureDefines.h"
#include "SkString.h"
#include "SkBitmap.h"
#include "SkCanvas.h"
#include "SkPaint.h"
#include "SkImage.h"
#include "SkDevice.h"
#include "SkPath.h"
#include "SkPoint.h"
#include "SkRect.h"
#include "SkTypeface.h"
#include "SkImageEncoder.h"
#include "SkPngCodec.h"
#include "SkDashPathEffect.h"
#include "SkGradientShader.h"
const bool IS_SRGB = false;
USkiaBPLibrary::USkiaBPLibrary(const FObjectInitializer& ObjectInitializer)
: Super(ObjectInitializer)
{
}
void USkiaBPLibrary::CreateContext(float imageWidth, float imageHeight, FSkiaContext& context, FLinearColor color, bool createTexture)
{
if ((imageWidth <= 0) || (imageHeight <= 0)) return;
//w & h
context.imageWidth = imageWidth;
context.imageHeight = imageHeight;
//bitmap
context.bitmap.bitmap = std::make_shared<SkBitmap>();
SkImageInfo image_info = SkImageInfo::Make((int)imageWidth, imageHeight, kBGRA_8888_SkColorType, kPremul_SkAlphaType);
context.bitmap.bitmap->allocPixels(image_info, image_info.minRowBytes());
//canvas
context.canvas.canvas = std::make_shared<SkCanvas>(*context.bitmap.bitmap);
context.canvas.canvas->clear(color.ToFColor(IS_SRGB).DWColor());
if (createTexture)
{
//texture
context.texture = UTexture2D::CreateTransient(context.imageWidth, context.imageHeight, EPixelFormat::PF_B8G8R8A8);
context.texture->UpdateResource();
//data
context.region = std::make_shared<FUpdateTextureRegion2D>(0, 0, 0, 0, imageWidth, imageHeight);
context.data = std::make_shared<TArray<FColor>>();
context.data->Init(FColor(0, 0, 0, 255), imageWidth *imageHeight);
}
}
void USkiaBPLibrary::UpdateTexture(const FSkiaContext& context)
{
if (context.bitmap.bitmap && context.texture)
{
TArray<FColor>& Data = *context.data;
FMemory::Memcpy(Data.GetData(), context.bitmap.bitmap->getPixels(), context.bitmap.bitmap->computeByteSize());
// Update texture 2D
context.texture->UpdateTextureRegions(0, 1, context.region.get(), (uint32)(context.imageWidth * sizeof(uint32)), sizeof(uint32), (uint8*)Data.GetData(),
[](uint8*, const FUpdateTextureRegion2D*){});
}
}
#pragma region Convert
SkRect MakeRect(FVector2D position, FVector2D size)
{
SkRect rect;
rect.fLeft = position.X;
rect.fTop = position.Y;
rect.fRight = position.X + size.X;
rect.fBottom = position.Y + size.Y;
return rect;
}
SkPoint MakePoint(FVector2D point)
{
return SkPoint::Make(point.X, point.Y);
}
#pragma endregion
#pragma region Paint
void USkiaBPLibrary::CreatePaint(FSkiaPaint& paint)
{
paint.paint = std::make_shared<SkPaint>();
//paint.paint->setLCDRenderText(true);
}
const FSkiaPaint& USkiaBPLibrary::SetPaintStyle(const FSkiaPaint& paint, EPaintStyle style, EPaintCap cap, EPaintJoin join)
{
paint.paint->setStyle((SkPaint::Style)style);
paint.paint->setStrokeCap((SkPaint::Cap)cap);
paint.paint->setStrokeJoin((SkPaint::Join)join);
return paint;
}
const FSkiaPaint& USkiaBPLibrary::SetPaintColor(const FSkiaPaint& paint, FLinearColor color)
{
paint.paint->setColor(color.ToFColor(IS_SRGB).DWColor());
return paint;
}
const FSkiaPaint& USkiaBPLibrary::SetPaintStrokeWidth(const FSkiaPaint& paint, int width)
{
paint.paint->setStrokeWidth(width);
return paint;
}
const FSkiaPaint& USkiaBPLibrary::SetPathEffect(const FSkiaPaint& paint, const TArray<float>& intervals, float phase)
{
paint.paint->setPathEffect(SkDashPathEffect::Make(intervals.GetData(), intervals.Num(), phase));
return paint;
}
const FSkiaPaint& USkiaBPLibrary::SetTypeFace(const FSkiaPaint& paint, FString familyName, EFontType fontType)
{
switch (fontType)
{
case EFontType::Font_Normal:
paint.paint->setTypeface(SkTypeface::MakeFromName(TCHAR_TO_UTF8(*familyName), SkFontStyle::Normal()));
break;
case EFontType::Font_Bold:
paint.paint->setTypeface(SkTypeface::MakeFromName(TCHAR_TO_UTF8(*familyName), SkFontStyle::Bold()));
break;
case EFontType::Font_Italic:
paint.paint->setTypeface(SkTypeface::MakeFromName(TCHAR_TO_UTF8(*familyName), SkFontStyle::Italic()));
break;
case EFontType::Font_BoldItalic:
paint.paint->setTypeface(SkTypeface::MakeFromName(TCHAR_TO_UTF8(*familyName), SkFontStyle::BoldItalic()));
break;
default:
break;
}
return paint;
}
const FSkiaPaint& USkiaBPLibrary::SetPaintTextAlign(const FSkiaPaint& paint, EPaintAlign textAlign)
{
paint.paint->setTextAlign((SkPaint::Align)textAlign);
return paint;
}
const FSkiaPaint& USkiaBPLibrary::SetPaintTextSize(const FSkiaPaint& paint, float textSize)
{
paint.paint->setTextSize(textSize);
return paint;
}
const FSkiaPaint& USkiaBPLibrary::SetPaintAntiAlias(const FSkiaPaint& paint, bool antiAlias)
{
paint.paint->setAntiAlias(antiAlias);
return paint;
}
const FSkiaPaint& USkiaBPLibrary::SetPaintTextScaleX(const FSkiaPaint& paint, float scale)
{
paint.paint->setTextScaleX(scale);
return paint;
}
const FSkiaPaint& USkiaBPLibrary::SetPaintTextSkewX(const FSkiaPaint& paint, float scale)
{
paint.paint->setTextSkewX(scale);
return paint;
}
const FSkiaPaint& USkiaBPLibrary::MeasureText(const FSkiaPaint& paint, const FString& text, FSkiaRect& rect)
{
std::string str = TCHAR_TO_UTF8(*text);
SkRect r;
paint.paint->measureText(str.c_str(), str.length(), &r);
rect.point = FVector2D(r.left(), r.top());
rect.size = FVector2D(r.width(), r.height());
return paint;
}
const FSkiaPaint& USkiaBPLibrary::SetPaintGradientLiner(const FSkiaPaint& paint, FVector2D start, FVector2D end, TArray<FSkiaGradient> gradients, EPaintTileMode mode)
{
SkPoint pts[2]{ MakePoint(start), MakePoint(end) };
TArray<SkColor> colors;
TArray<SkScalar> pos;
for (size_t i = 0; i < gradients.Num(); i++)
{
colors.Add(gradients[i].color.ToFColor(IS_SRGB).DWColor());
pos.Add(gradients[i].offset);
}
sk_sp<SkShader> shade = SkGradientShader::MakeLinear(pts, colors.GetData(), pos.GetData(), colors.Num(), (SkShader::TileMode)mode);
paint.paint->setShader(shade);
return paint;
}
const FSkiaPaint& USkiaBPLibrary::SetPaintGradientRadial(const FSkiaPaint& paint, FVector2D center, float radius, TArray<FSkiaGradient> gradients, EPaintTileMode mode)
{
TArray<SkColor> colors;
TArray<SkScalar> pos;
for (size_t i = 0; i < gradients.Num(); i++)
{
colors.Add(gradients[i].color.ToFColor(IS_SRGB).DWColor());
pos.Add(gradients[i].offset);
}
sk_sp<SkShader> shade = SkGradientShader::MakeRadial(MakePoint(center), radius, colors.GetData(), pos.GetData(), colors.Num(), (SkShader::TileMode)mode);
paint.paint->setShader(shade);
return paint;
}
const FSkiaPaint& USkiaBPLibrary::SetPaintGradientSweep(const FSkiaPaint& paint, FVector2D center, TArray<FSkiaGradient> gradients)
{
TArray<SkColor> colors;
TArray<SkScalar> pos;
for (size_t i = 0; i < gradients.Num(); i++)
{
colors.Add(gradients[i].color.ToFColor(IS_SRGB).DWColor());
pos.Add(gradients[i].offset);
}
sk_sp<SkShader> shade = SkGradientShader::MakeSweep(center.X, center.Y, colors.GetData(), pos.GetData(), colors.Num());
paint.paint->setShader(shade);
return paint;
}
#pragma endregion
#pragma region Drawing
void USkiaBPLibrary::Translate(const FSkiaCanvas& canvas, float dx, float dy)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->translate(dx, dy);
}
}
void USkiaBPLibrary::Scale(const FSkiaCanvas& canvas, float sx, float sy)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->scale(sx, sy);
}
}
void USkiaBPLibrary::Rotate(const FSkiaCanvas& canvas, float angle)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->rotate(angle * PI / 180);
}
}
void USkiaBPLibrary::Rotate2(const FSkiaCanvas& canvas, float angle, float px, float py)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->rotate(angle * PI / 180, px, py);
}
}
void USkiaBPLibrary::Skew(const FSkiaCanvas& canvas, float sx, float sy)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->skew(sx, sy);
}
}
void USkiaBPLibrary::DrawColor(const FSkiaCanvas& canvas, FLinearColor color, ECanvasBlendMode mode)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->drawColor(color.ToFColor(IS_SRGB).DWColor(), (SkBlendMode)mode);
}
}
void USkiaBPLibrary::Clear(const FSkiaCanvas& canvas, FLinearColor color)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->clear(color.ToFColor(IS_SRGB).DWColor());
}
}
void USkiaBPLibrary::DrawPaint(const FSkiaCanvas& canvas, const FSkiaPaint& paint)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->drawPaint(*paint.paint);
}
}
void USkiaBPLibrary::DrawPoint(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D point)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->drawPoint(MakePoint(point), *paint.paint);
}
}
void USkiaBPLibrary::DrawPoints(const FSkiaCanvas& canvas, const FSkiaPaint& paint, ECanvasPointMode mode, TArray<FVector2D> points)
{
if (canvas.canvas != nullptr)
{
TArray<SkPoint> pts;
for (size_t i = 0; i < points.Num(); i++)
{
pts.Add(MakePoint(points[i]));
}
canvas.canvas->drawPoints((SkCanvas::PointMode)mode, pts.Num(), pts.GetData(), *paint.paint);
}
}
void USkiaBPLibrary::DrawLine(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D p0, FVector2D p1)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->drawLine(MakePoint(p0), MakePoint(p1), *paint.paint);
}
}
void USkiaBPLibrary::DrawLine2(const FSkiaCanvas& canvas, const FSkiaPaint& paint, const FSkiaLine& line)
{
DrawLine(canvas, paint, line.p0, line.p1);
}
void USkiaBPLibrary::DrawPolyline(const FSkiaCanvas& canvas, const FSkiaPaint& paint, TArray<FVector2D> points, bool closed)
{
if (canvas.canvas != nullptr)
{
TArray<SkPoint> pts;
for (size_t i = 0; i < points.Num(); i++)
{
pts.Add(MakePoint(points[i]));
}
SkPath path;
path.addPoly(pts.GetData(), pts.Num(), closed);
canvas.canvas->drawPath(path, *paint.paint);
}
}
void USkiaBPLibrary::DrawRect(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D point, FVector2D size)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->drawRect(MakeRect(point, size), *paint.paint);
}
}
void USkiaBPLibrary::DrawRect2(const FSkiaCanvas& canvas, const FSkiaPaint& paint, const FSkiaRect& rect)
{
DrawRect(canvas, paint, rect.point, rect.size);
}
void USkiaBPLibrary::DrawRoundRect(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D point, FVector2D size, float rx, float ry)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->drawRoundRect(MakeRect(point, size), rx, ry, *paint.paint);
}
}
void USkiaBPLibrary::DrawArc(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D point, FVector2D size, float startAngle, float sweepAngle, bool useCenter)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->drawArc(MakeRect(point, size), startAngle, sweepAngle, useCenter, *paint.paint);
}
}
void USkiaBPLibrary::DrawArc2(const FSkiaCanvas& canvas, const FSkiaPaint& paint, const FSkiaArc& arc, bool useCenter)
{
DrawArc(canvas, paint, arc.point, arc.size, arc.startAngle, arc.sweepAngle, useCenter);
}
void USkiaBPLibrary::DrawOval(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D point, FVector2D size)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->drawOval(MakeRect(point, size), *paint.paint);
}
}
void USkiaBPLibrary::DrawCircle(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D center, float radius)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->drawCircle(MakePoint(center), radius, *paint.paint);
}
}
void USkiaBPLibrary::DrawCircle2(const FSkiaCanvas& canvas, const FSkiaPaint& paint, const FSkiaCircle& circle)
{
DrawCircle(canvas, paint, circle.center, circle.radius);
}
FSkiaRect USkiaBPLibrary::DrawText(const FSkiaCanvas& canvas, const FSkiaPaint& paint, FVector2D point, FString text)
{
FSkiaRect rect;
if (canvas.canvas != nullptr)
{
std::string str = TCHAR_TO_UTF8(*text);
canvas.canvas->drawText(str.c_str(), str.length(), point.X, point.Y, *paint.paint);
MeasureText(paint, text, rect);
rect.point += point;
}
return rect;
}
void USkiaBPLibrary::ClipRect(const FSkiaCanvas& canvas, FVector2D point, FVector2D size, EClipOp op, bool doAntiAlias)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->clipRect(MakeRect(point, size), (SkClipOp)op, doAntiAlias);
}
}
void USkiaBPLibrary::ClipPath(const FSkiaCanvas& canvas, const FSkiaPath& path, EClipOp op, bool doAntiAlias)
{
if (canvas.canvas != nullptr)
{
canvas.canvas->clipPath(*path.path, (SkClipOp)op, doAntiAlias);
}
}
void USkiaBPLibrary::CreateBitmap(FString filePath, FSkiaBitmap& bitmap)
{
SkCodec::Result result;
std::unique_ptr<SkCodec> codec = SkPngCodec::MakeFromStream(SkFILEStream::MakeFromFile(TCHAR_TO_UTF8(*filePath)), &result);
const SkImageInfo& image_info = codec->getInfo();
std::shared_ptr<SkBitmap> image = std::make_shared<SkBitmap>();
image->allocPixels(image_info);
result = codec->getPixels(image_info, image->getPixels(), image->rowBytes());
if (SkCodec::kSuccess == result)
{
bitmap.bitmap = image;
bitmap.imageWidth = image->width();
bitmap.imageHeight = image->height();
}
}
void USkiaBPLibrary::DrawBitmap(const FSkiaCanvas& canvas, const FSkiaBitmap& bitmap, FVector2D point)
{
if ((canvas.canvas != nullptr) && (bitmap.bitmap != nullptr))
{
canvas.canvas->drawBitmap(*bitmap.bitmap, point.X, point.Y);
}
}
#pragma endregion
#pragma region Path
void USkiaBPLibrary::CreatePath(FSkiaPath& path)
{
path.path = std::make_shared<SkPath>();
}
void USkiaBPLibrary::MoveTo(const FSkiaPath& path, FVector2D point)
{
path.path->moveTo(point.X, point.Y);
}
void USkiaBPLibrary::LineTo(const FSkiaPath& path, FVector2D point)
{
path.path->lineTo(point.X, point.Y);
}
void USkiaBPLibrary::QuadTo(const FSkiaPath& path, FVector2D pt1, FVector2D pt2)
{
path.path->quadTo(MakePoint(pt1), MakePoint(pt2));
}
void USkiaBPLibrary::ConicTo(const FSkiaPath& path, FVector2D pt1, FVector2D pt2, float w)
{
path.path->conicTo(MakePoint(pt1), MakePoint(pt2), w);
}
void USkiaBPLibrary::CubicTo(const FSkiaPath& path, FVector2D pt1, FVector2D pt2, FVector2D pt3)
{
path.path->cubicTo(MakePoint(pt1), MakePoint(pt2), MakePoint(pt3));
}
void USkiaBPLibrary::ArcTo(const FSkiaPath& path, FVector2D point, FVector2D size, float startAngle, float sweepAngle, bool forceMoveTo)
{
path.path->arcTo(MakeRect(point, size), startAngle, sweepAngle, forceMoveTo);
}
void USkiaBPLibrary::ArcTo2(const FSkiaPath& path, FVector2D pt1, FVector2D pt2, float radius)
{
path.path->arcTo(MakePoint(pt1), MakePoint(pt2), radius);
}
void USkiaBPLibrary::DrawPath(const FSkiaCanvas& canvas, const FSkiaPaint& paint, const FSkiaPath& path, bool closed, EPathFillType fillType)
{
if (canvas.canvas != nullptr)
{
if (closed)
{
path.path->close();
}
path.path->setFillType((SkPath::FillType)fillType);
canvas.canvas->drawPath(*path.path, *paint.paint);
}
}
#pragma endregion
网友评论