美文网首页
UE4封装Skia

UE4封装Skia

作者: qlaiaqu | 来源:发表于2019-02-20 17:48 被阅读0次

    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
    

    相关文章

      网友评论

          本文标题:UE4封装Skia

          本文链接:https://www.haomeiwen.com/subject/izahyqtx.html