Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

linux/arm64 support (including a Rust rewrite) #2261

Draft
wants to merge 153 commits into
base: master
Choose a base branch
from

Conversation

RedstoneWizard08
Copy link

@RedstoneWizard08 RedstoneWizard08 commented Jun 23, 2023

Thanks for contributing!

  • Have you updated CHANGELOG.md?

Would likely fix: #2074 #1662

Milestones:

  • Consistently successful prebuild image CI builds!
  • Some successful bundle builds
  • Successful bundle builds
  • Consistently successful bundle builds

Implementation Checklist

  • Canvas
    • new()
      • new(width: i32, height: i32)
      • new(width: i32, height: i32, kind: ImageKind)
    • toBuffer()
      • toBuffer(cb: fn(Option, Buffer))
      • toBuffer(cb: fn(Option, Buffer), mime: String)
      • toBuffer(cb: fn(Option, Buffer), mime: String, config: BufferConfig)
      • toBuffer() -> Buffer
      • toBuffer(mime: String) -> Buffer
      • toBuffer(mime: String, config: BufferConfig) -> Buffer
      • mime = "image/png" (default on non-PDF, non-SVG canvases)
      • mime = "image/jpeg"
      • mime = "raw" (Unencoded BGRA data on LE, ARGB on BE, top-to-bottom)
      • mime = "application/pdf" (only for PDF canvases)
      • mime = "image/svg+xml" (only for SVG canvases)
    • createPNGStream()
      • createPNGStream() -> ReadableStream
      • createPNGStream(config: PngConfig) -> ReadableStream
    • createJPEGStream()
      • createJPEGStream() -> ReadableStream
      • createJPEGStream(config: JpegConfig) -> ReadableStream
    • createPDFStream()
      • createPDFStream() -> ReadableStream
      • createPDFStream(config: PdfConfig) -> ReadableStream
    • toDateURL()
      • toDataURL() -> String
      • toDataURL(mime: String) -> String
      • toDataURL(mime: String, quality: f32 /* 0 to 1 */) -> String
      • toDataURL(cb: fn(Option, String))
      • toDataURL(mime: String, cb: fn(Option, String))
      • toDataURL(mime: String, opts: BufferConfig, cb: fn(Option, String))
      • toDataURL(mime: String, quality: f32 /* 0 to 1 */, cb: fn(Option, String))
      • mime = "image/png"
      • mime = "image/jpeg"
    • width: i32
    • height: i32
    • stride: i32
    • getContext()
      • getContext(id: String)
      • getContext(id: String, attrs: ContextSettings) -> CanvasRenderingContext2D
      • id = "2d"
      • id = "webgl"
      • id = "webgl2"
  • CanvasRenderingContext2D
    • clearRect(x: i32, y: i32, w: i32, h: i32)
    • fillRect(x: i32, y: i32, w: i32, h: i32)
    • strokeRect(x: i32, y: i32, w: i32, h: i32)
    • fillText()
      • fillText(text: String, x: i32, y: i32)
      • fillText(text: String, x: i32, y: i32, maxWidth: i32)
    • strokeText()
      • strokeText(text: String, x: i32, y: i32)
      • strokeText(text: String, x: i32, y: i32, maxWidth: i32)
    • measureText(text: String) -> TextMetrics
    • getLineDash() -> Vec
    • setLineDash(segments: Vec)
    • createLinearGradient(x0: i32, y0: i32, x1: i32, y1: i32) -> CanvasGradient
    • createRadialGradient(x0: i32, y0: i32, r0: i32, x1: i32, y1: i32, r1: i32) -> CanvasGradient
    • createPattern()
      • createPattern(image: Either<Canvas, Image>) -> CanvasPattern
      • createPattern(image: Either<Canvas, Image>, repetition: Repetition) -> CanvasPattern
    • beginPath()
    • closePath()
    • moveTo(x: i32, y: i32)
    • lineTo(x: i32, y: i32)
    • quadraticCurveTo(cpx: i32, cpy: i32, x: i32, y: i32)
    • bezierCurveTo(cp1x: i32, cp1y: i32, cp2x: i32, cp2y: i32, x: i32, y: i32)
    • arc()
      • arc(x: i32, y: i32, radius: i32, startAngle: i32, endAngle: i32)
      • arc(x: i32, y: i32, radius: i32, startAngle: i32, endAngle: i32, counterClockwise: bool)
    • arcTo(x1: i32, y1: i32, x2: i32, y2: i32, radius: i32)
    • ellipse()
      • ellipse(x: i32, y: i32, radiusX: i32, radiusY: i32, rotation: i32, startAngle: i32, endAngle: i32)
      • ellipse(x: i32, y: i32, radiusX: i32, radiusY: i32, rotation: i32, startAngle: i32, endAngle: i32, counterclockwise: bool)
    • rect(x: i32, y: i32, w: i32, h: i32)
    • roundRect()
      • roundRect(x: i32, y: i32, w: i32, h: i32)
      • roundRect(x: i32, y: i32, w: i32, h: i32, radii: i32)
      • roundRect(x: i32, y: i32, w: i32, h: i32, radii: [i32; 4])
    • fill()
      • fill()
      • fill(fillRule: CanvasFillRule)
    • stroke()
    • clip()
      • clip()
      • clip(fillRule: CanvasFillRule)
    • isPointInPath()
      • isPointInPath(x: i32, y: i32)
      • isPointInPath(x: i32, y: i32, fillRule: CanvasFillRule)
    • rotate(angle: f32)
    • scale(x: f32, y: f32)
    • translate(x: i32, y: i32)
    • transform(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32)
    • setTransform()
      • setTransform()
      • setTransform(transform: DomMatrix)
      • setTransform(a: i32, b: i32, c: i32, d: i32, e: i32, f: i32)
    • getTransform() -> DomMatrix
    • resetTransform()
    • drawImage()
      • drawImage(image: Either<Canvas, Image>, dx: i32, dy: i32)
      • drawImage(image: Either<Canvas, Image>, dx: i32, dy: i32, dw: i32, dh: i32)
      • drawImage(image: Either<Canvas, Image>, sx: i32, sy: i32, sw: i32, sh: i32, dx: i32, dy: i32, dw: i32, dh: i32)
    • createImageData()
      • createImageData(sw: i32, sh: i32) -> ImageData
      • createImageData(data: ImageData) -> ImageData
    • getImageData(sx: i32, sy: i32, sw: i32, sh: i32) -> ImageData
    • putImageData()
      • putImageData(data: ImageData, dx: i32, dy: i32)
      • putImageData(data: ImageData, dx: i32, dy: i32, dirtyX: i32, dirtyY: i32, dirtyWidth: i32, dirtyHeight: i32)
    • save()
    • restore()
    • addPage() /* PDF Only */
      • addPage()
      • addPage(w: i32)
      • addPage(w: i32, h: i32)
    • patternQuality: Quality = Quality::Good
    • quality: Quality = Quality::Good
    • textDrawingMode: TextDrawingMode = TextDrawingMode::Path
    • antialias: AliasingMode = AliasingMode::Default
    • lineWidth: i32
    • lineCap: LineCap
    • lineJoin: LineJoin
    • miterLimit: i32
    • lineDashOffset: i32
    • font: String
    • textAlign: TextAlign
    • textBaseline: TextBaseline
    • fillStyle: Either3<String, CanvasGradient, CanvasPattern>
    • strokeStyle: Either3<String, CanvasGradient, CanvasPattern>
    • shadowBlur: i32
    • shadowColor: String
    • shadowOffsetX: i32
    • shadowOffsetY: i32
    • currentTransform: DomMatrix
    • globalAlpha: i32
    • globalCompositeOperation: GlobalCompositeOperation
    • imageSmoothingEnabled: bool
    • canvas: Canvas
  • ImageData
    • new()
      • new(width: i32, height: i32)
      • new(data: Uint8ClampedArray, width: i32)
      • new(data: Uint8ClampedArray, width: i32, height: i32)
    • data: Uint8ClampedArray
    • width: i32
    • height: i32
  • CanvasGradient
    • [] addColorStop(offset: i32, color: String)
  • CanvasPattern
    • setTransform()
      • setTransform()
      • setTransform(matrix: DomMatrix)
  • Image
    • src: Either<String, Buffer>
    • dataMode: ImageMode
    • width: i32
    • height: i32
    • complete: bool
    • naturalWidth: i32
    • naturalHeight: i32
  • DomMatrix
    • new()
      • new(init: String)
      • new(init: Vec)
    • toString()
    • multiply(other: DomMatrix) -> DomMatrix
    • multiplySelf(other: DomMatrix) -> DomMatrix
    • preMultiplySelf(other: DomMatrix) -> DomMatrix
    • translate(tx: i32, ty: i32, tz: i32) -> DomMatrix
    • translateSelf(tx: i32, ty: i32, tz: i32) -> DomMatrix
    • scale(scaleX: i32, scaleY: i32, scaleZ: i32, originX: i32, originY: i32, originZ: i32) -> DomMatrix
    • scale3d(scale: i32, originX: i32, originY: i32, originZ: i32) -> DomMatrix
    • scale3dSelf(scale: i32, originX: i32, originY: i32, originZ: i32) -> DomMatrix
    • scaleSelf(scaleX: i32, scaleY: i32, scaleZ: i32, originX: i32, originY: i32, originZ: i32) -> DomMatrix
    • rotateFromVector(x: i32, y: i32) -> DomMatrix
    • rotateFromVectorSelf(x: i32, y: i32) -> DomMatrix
    • rotate(rotX: i32, rotY: i32, rotZ: i32) -> DomMatrix
    • rotateSelf(rotX: i32, rotY: i32, rotZ: i32) -> DomMatrix
    • rotateAxisAngle(x: i32, y: i32, z: i32, angle: i32) -> DomMatrix
    • rotateAxisAngleSelf(x: i32, y: i32, z: i32, angle: i32) -> DomMatrix
    • skewX(sx: i32) -> DomMatrix
    • skewXSelf(sx: i32) -> DomMatrix
    • skewY(sy: i32) -> DomMatrix
    • skewYSelf(sy: i32) -> DomMatrix
    • flipX() -> DomMatrix
    • flipY() -> DomMatrix
    • inverse() -> DomMatrix
    • invertSelf() -> DomMatrix
    • setMatrixValue(transformList: string) -> DomMatrix
    • transformPoint(point: DomPoint) -> DomPoint
    • toFloat32Array() -> Float32Array
    • toFloat64Array() -> Float64Array
    • is2D: bool
    • isIdentity: bool
    • a: i32
    • b: i32
    • c: i32
    • d: i32
    • e: i32
    • f: i32
    • m11: i32
    • m12: i32
    • m13: i32
    • m14: i32
    • m21: i32
    • m22: i32
    • m23: i32
    • m24: i32
    • m31: i32
    • m32: i32
    • m33: i32
    • m34: i32
    • m41: i32
    • m42: i32
    • m43: i32
    • m44: i32
    • + Traits:
      • std::ops::Mul
      • std::ops::MulAssign
      • std::ops::Add
      • std::ops::AddAssign
      • std::ops::Div
      • std::ops::DivAssign
      • std::ops::Sub
      • std::ops::SubAssign
      • From
      • From
      • From
  • DomPoint
    • w: i32
    • x: i32
    • y: i32
    • z: i32
  • enum FillRule
    • EvenOdd
    • NonZero
  • enum Repetition
    • Repeat
    • RepeatX
    • RepeatY
    • NoRepeat
    • None
  • enum TextAlign
    • Center
    • End
    • Left
    • Right
    • Start
  • enum TextBaseline
    • Alphabetic
    • Bottom
    • Hanging
    • Ideographic
    • Middle
    • Top
  • enum LineCap
    • Butt
    • Round
    • Square
  • enum LineJoin
    • Bevel
    • Miter
    • Round
  • enum GlobalCompositeOperation
    • Clear
    • Copy
    • Destination
    • SourceOver
    • DestinationOver
    • SourceIn
    • DestinationIn
    • SourceOut
    • DestinationOut
    • SourceAtop
    • DestinationAtop
    • Xor
    • Lighter
    • Normal
    • Multiply
    • Screen
    • Overlay
    • Darken
    • Lighten
    • ColorDodge
    • ColorBurn
    • HardLight
    • SoftLight
    • Difference
    • Exclusion
    • Hue
    • Saturation
    • Color
    • Luminosity
    • Saturate
  • TextMetrics
    • actualBoundingBoxAscent: i32
    • actualBoundingBoxDescent: i32
    • actualBoundingBoxLeft: i32
    • actualBoundingBoxRight: i32
    • fontBoundingBoxAscent: i32
    • fontBoundingBoxDescent: i32
    • width: i32
  • enum ImageKind
    • Image
    • Pdf
    • Svg
  • enum ImageMode (bitflags)
    • Image = 0
    • Mime = 1
  • struct FontOptions (builder)
    • family: String
    • weight: Option,
    • style: Option,
  • enum BufferConfig (builder)
    • Jpeg(JpegConfig)
    • Png(PngConfig)
    • Pdf(PdfConfig)
  • enum PngFilters (bitflags)
    • NoFilters = 0
    • All = 1
    • None = 2
    • Sub = 3
    • Up = 4
    • Avg = 5
    • Paeth = 6
  • struct JpegConfig
    • quality: f32 = 0.75
    • progressive: bool = false
    • chromaSubsampling: bool = true
  • struct PngConfig
    • compressionLevel: u8 = 6
    • filters: u8 = PngFilters::All
    • palette: Option<{unknown}>
    • backgroundIndex: i32
    • resolution: Option<{unknown}>
  • struct PdfConfig
    • title: Option
    • author: Option
    • subject: Option
    • keywords: Option
    • creator: Option
    • creationDate: Date
    • modDate: Option
  • enum Quality
    • Fast
    • Good
    • Best
    • Nearest
    • Bilinear
  • enum TextDrawingMode
    • Path
    • Glyph
  • enum AliasingMode
    • Default
    • None
    • Gray
    • Subpixel
  • enum PixelFormat
    • Rgba32
    • Rgb24
    • A8
    • Rgb16_565
    • A1
    • Rgb30
  • struct ContextSettings
    • alpha: bool = false
    • pixelFormat: Option
  • createCanvas()
    • createCanvas(width: i32, height: i32) -> Canvas
    • createCanvas(width: i32, height: i32, kind: ImageKind) -> Canvas
  • createImageData()
    • createImageData(width: i32, height: i32) -> ImageData
    • createImageData(data: Uint8ClampedArray, width: i32) -> ImageData
    • createImageData(data: Uint8ClampedArray, width: i32, height: i32) -> ImageData
    • createImageData(data: Vec, width: i32) -> ImageData
    • createImageData(data: Vec, width: i32, height: i32) -> ImageData
  • async loadImage(url: string) -> Image
  • registerFont(path: string, opts: FontOptions)

@zbjornson
Copy link
Collaborator

@RedstoneWizard08 rewriting node-canvas in Rust is most likely out of scope for this repository. There's also a Rust-based Skia binding already that you might be interested in: https://www.npmjs.com/package/@napi-rs/canvas.

@RedstoneWizard08
Copy link
Author

@zbjornson Yes, I am aware that that exists, but the idea was to create a portable drop-in replacement for the existing C++ version, allowing the existing API to be supported on many more platforms. Since C++ was giving me a lot of issues (100+ commits worth of band-aid fixes and issues), I decided to rewrite it with a pure-rust implementation so it would be easier to cross-compile.

@RedstoneWizard08
Copy link
Author

The skia version also is not pure-rust, meaning it is harder to compile for other systems.

@7f8ddd
Copy link

7f8ddd commented Jan 9, 2024

The skia version also is not pure-rust, meaning it is harder to compile for other systems.

Make it, ignore that guy, it's still cool.
And make sure you publish a release instead of making people who need NAPI have to build it, lol.

Ask ChatGPT if you get stuck on something math related, it might help.

@RedstoneWizard08
Copy link
Author

RedstoneWizard08 commented Jan 10, 2024

And make sure you publish a release instead of making people who need NAPI have to build it, lol.

Yeah, I definitely will.

@elysiumplain
Copy link

elysiumplain commented Jan 11, 2024

Just ran into this while trying to build a Rust re-write project on arm64 architecture.

I come from a long history of run-anywhere programming languages and am now discovering what pains may have led early developers to go take such an approach as the concept of distributed contributions (multi-arch) grew.

Would hate to have to suggest migrating over to Skia as a patch! Happy to see that at least the request is active.

@RedstoneWizard08
Copy link
Author

@elysiumplain thanks! I did consider using Skia, but I decided not to, since Skia is still C with Rust, and I want this to be pure rust for maximum compatibility. I do know that tiny-skia exists, but I don't think it supports the features I need yet. Thanks though!

@RedstoneWizard08
Copy link
Author

Also I've been really busy with school and I have finals in 2 weeks so I haven't had a lot of time, I'm trying to keep working on it.

@RedstoneWizard08
Copy link
Author

Also @7f8ddd ChatGPT wasn't too helpful xD
I might try again with it soon

1 similar comment
@RedstoneWizard08
Copy link
Author

Also @7f8ddd ChatGPT wasn't too helpful xD
I might try again with it soon

@7f8ddd
Copy link

7f8ddd commented Jan 12, 2024

Also @7f8ddd ChatGPT wasn't too helpful xD I might try again with it soon

Might be able to get help in a graphics programming Discord. There are servers all about this kinda stuff with people who probably understand it.

@RedstoneWizard08
Copy link
Author

Any you recommend?

@RedstoneWizard08
Copy link
Author

HOLY CRAP I JUST FIXED THE MATRIX LETS GOOOO

@RedstoneWizard08
Copy link
Author

The issue was my bad logic in assuming that overwriting variable names wouldn't change anything. I was wrong.

@RedstoneWizard08
Copy link
Author

btw all tests are passing (not all are implemented yet tho)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Installing canvas giving error on Pterodactyl server (linux arm64)
5 participants