Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion gtk4/inc/TGtk4PadPainter.h
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,9 @@ friend class TGtk4Canvas;
void DrawPolyMarker(Int_t n, const Double_t *x, const Double_t *y) override;
void DrawPolyMarker(Int_t n, const Float_t *x, const Float_t *y) override;

void DrawTTFglyphs(Int_t x, Int_t y, TTFhandle &ttf, ETextMode mode) override;
void DrawTTFglyphs(Int_t x, Int_t y, TTFhandle &ttf, ETextMode mode) override;

void DrawImage(TImage *img, Int_t x, Int_t y, Int_t flags = 0) override;

Bool_t IsSupportAlpha() const override { return kTRUE; }

Expand Down
34 changes: 33 additions & 1 deletion gtk4/src/TGtk4PadPainter.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,16 @@
#include "TROOT.h"
#include "TColor.h"
#include "RStipples.h"

#include "TTFhandle.h"
#include "TImage.h"

#include <memory>
#include <map>

#include "Gtk4DrawArea.h"

#include <cairomm/context.h>
#include <cairomm/surface.h>
#include <cairo.h>


Expand Down Expand Up @@ -553,3 +554,34 @@ void TGtk4PadPainter::DrawTTFglyphs(Int_t px, Int_t py, TTFhandle &ttf, ETextMod
ctx->mask(surface, px + bx, py + by);
}
}


////////////////////////////////////////////////////////////////////////////////
/// Render TTF glyphs on drawable area

void TGtk4PadPainter::DrawImage(TImage *img, Int_t px, Int_t py, Int_t)
{
// position inside the pad is provided, therefore shift it to global image
px += fPad->UtoAbsPixel(0);
py += fPad->VtoAbsPixel(1);

auto width = img->GetWidth();
auto height = img->GetHeight();
auto argbBuffer = (unsigned char*) img->GetArgbArray();

auto ctx = fDrawArea->GetContext();

int stride = Cairo::ImageSurface::format_stride_for_width(Cairo::Surface::Format::ARGB32, width);

// 2. Wrap your raw memory pointer into a Cairo Surface.
// This borrows the memory pointer without making a deep copy.
Cairo::RefPtr<Cairo::ImageSurface> surface =
Cairo::ImageSurface::create(argbBuffer, Cairo::Surface::Format::ARGB32, width, height, stride);

// 3. Set the surface as the source pattern in the context
// (0, 0) specifies the top-left offset to place the image
ctx->set_source(surface, px, py);

// 4. Paint the pattern onto the context canvas
ctx->paint();
}
2 changes: 2 additions & 0 deletions qt6/inc/TQt6PadPainter.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ friend class TQt6Canvas;

void DrawTTFglyphs(Int_t px, Int_t py, TTFhandle &ttf, [[maybe_unused]] ETextMode mode) override;

void DrawImage(TImage *img, Int_t x, Int_t y, Int_t flags = 0) override;

private:
//Let's make this clear:
TQt6PadPainter(const TQt6PadPainter &rhs) = delete;
Expand Down
38 changes: 33 additions & 5 deletions qt6/src/TQt6PadPainter.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -19,18 +19,16 @@
#include "TROOT.h"
#include "TColor.h"
#include "RStipples.h"
#include "TTFhandle.h"
#include "TImage.h"

#include <memory>
#include <map>

#include "QPaintWidget.h"

#include "TTFhandle.h"


#include <QFont>
#include <QFontDatabase>
#include <QRect>
#include <QImage>
#include <QPainter>

using namespace ROOT::Experimental;
Expand Down Expand Up @@ -492,3 +490,33 @@ void TQt6PadPainter::DrawTTFglyphs(Int_t px, Int_t py, TTFhandle &ttf, [[maybe_u
}
}

void TQt6PadPainter::DrawImage(TImage *img, Int_t px, Int_t py, Int_t)
{
// position inside the pad is provided, therefore shift it to global image
px += fPad->UtoAbsPixel(0);
py += fPad->VtoAbsPixel(1);

auto width = img->GetWidth();
auto height = img->GetHeight();
auto argbBuffer = (const uchar*) img->GetArgbArray();

auto painter = fPaintWidget->getPainter();

int bytesPerLine = width * 4;

// 1. Wrap the raw memory array into a QImage.
// This constructor does NOT copy the pixel data; it points directly to your buffer.
QImage image(
argbBuffer,
width,
height,
bytesPerLine,
QImage::Format_ARGB32
);

// 2. Draw the image using QPainter
// (0, 0) is the top-left coordinate where the image will be drawn
painter->drawImage(px, py, image);
}


2 changes: 2 additions & 0 deletions raylib/inc/TRaylibPadPainter.h
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@ friend class TRaylibCanvas;

void DrawTTFglyphs(Int_t px, Int_t py, TTFhandle &ttf, [[maybe_unused]] ETextMode mode) override;

void DrawImage(TImage *img, Int_t x, Int_t y, Int_t flags = 0) override;

private:
TRaylibPadPainter(const TRaylibPadPainter &) = delete;
TRaylibPadPainter(TRaylibPadPainter &&) = delete;
Expand Down
54 changes: 52 additions & 2 deletions raylib/src/TRaylibPadPainter.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@
#include "TPoint.h"
#include "TROOT.h"
#include "TColor.h"

#include "RStipples.h"
#include "TTFhandle.h"
#include "TImage.h"


#include <raylib.h>
Expand Down Expand Up @@ -501,6 +500,57 @@ void TRaylibPadPainter::DrawTTFglyphs(Int_t px, Int_t py, TTFhandle &ttf, [[mayb
}
}

////////////////////////////////////////////////////////////////////////////////
/// Render image on drawable area

void TRaylibPadPainter::DrawImage(TImage *img, Int_t px, Int_t py, Int_t)
{
px += fPad->UtoAbsPixel(0);
py += fPad->VtoAbsPixel(1);

auto width = img->GetWidth();
auto height = img->GetHeight();
auto argbBuffer = (unsigned char*) img->GetArgbArray();

int pixelCount = width * height;

std::vector<unsigned char> rgbaData(pixelCount * 4);

// Convert ARGB/BGRA to RGBA in-memory
for (int i = 0; i < pixelCount; i++) {
int srcIdx = i * 4;
int dstIdx = i * 4;

// Assuming source is Cairo's Little-Endian BGRA format [B, G, R, A]:
rgbaData[dstIdx + 0] = argbBuffer[srcIdx + 2]; // Red
rgbaData[dstIdx + 1] = argbBuffer[srcIdx + 1]; // Green
rgbaData[dstIdx + 2] = argbBuffer[srcIdx + 0]; // Blue
rgbaData[dstIdx + 3] = argbBuffer[srcIdx + 3]; // Alpha
}

Image rayimg = {
.data = rgbaData.data(),
.width = (int)width,
.height = (int)height,
.mipmaps = 1,
.format =PIXELFORMAT_UNCOMPRESSED_R8G8B8A8
};

// Upload to GPU memory
Texture2D texture = LoadTextureFromImage(rayimg);

DrawTexture(texture, px, py, WHITE);

// Always unload transient textures to avoid GPU memory leaks!
// but we should wait until rendering is finished
fTextures.push_back(texture);
}



////////////////////////////////////////////////////////////////////////////////
/// Cleanup context

void TRaylibPadPainter::CleanupTextures()
{
for (auto &texture : fTextures)
Expand Down