Canvas is cool! - page 101

 
Dz Mak #:
I know, that's not what I meant. Everything works there except reading coordinates, events just need to be written by yourself. My panels are fully functional in the tester (EA type), only that you can't move them with the mouse, because I couldn't make it read coordinates by any castile, the tester just doesn't see the cursor, yes I would have found a solution, but alas the desire to do nonsense is gone.

I didn't understand
in the indicator in the tester the CHARTEVENT_MOUSE_MOVE event doesn't work, but the CHARTEVENT_CLICK event works, by which you can read the mouse coordinates. In this there is a possibility of control in the tester. I.e. when you move the mouse when the left mouse button is pressed, everything works.

 
Nikolai Semko #:

didn't understand
in the indicator in the tester the CHARTEVENT_MOUSE_MOVE event doesn't work, but the CHARTEVENT_CLICK event works, by which you can read the mouse coordinates. In this there is a possibility of control in the tester. I.e. when you move the mouse when the left mouse button is pressed, everything works.

You need to write events yourself, because chart event does not work in the tester, if the file is an Expert Advisor, but works in indicators. Instead of chart event in the tester you need to read the states of objects and environment, so you can manually write your own "chart event" for the tester, then any panel will work there. In fact, for the tester chart event is not needed at all, it is useless there, if it is an Expert Advisor.In short, everything can be made to work there, if you want.
 
Nikolai Semko #:

Nicholas hello!

I had a quick look through all this thread, but I didn't find the answer to my question!

Could you please tell me - HOW to make a normal "stroke" for text on Canvas :

(this mark is made on Canvas)

the whole point is that IF you make N copies of the text and place it "in a circle" around the main text, then with a large font size (more than 50 points ... and I have ^ 150 points) and multi-line inscription, 5-7 lines (logs on the screen),
then when you create OBJECTS - the laptop can and hang ..... I had to restart the terminal ... and on kanvas - the laptop is quiet, but the time to create such a text multiline label = 5 minutes !!!!

...optimised the code, now on kanvas it creates 7 lines of log in 101 seconds (a little longer than a minute).

this is still very long !

Are there any ways or methods to create a faster stroke for text ?!!!

(I've seen this trick before - create a Canvas 1 time, and in it change sizes / pixels / colours ...) .... I'll try it, I'll report back later, ...
... but for now I'm still interested in the opinions of experts on this issue !

Thank you!

 
Vitaliy Kostrubko #:
Could you please tell me HOW to make a normal "stroke" for text on kanvas?
I'm not an expert on kanvas. Most likely there are standard possibilities. But purely geometric idea - draw text on N% larger size in black, and on top of normal size in white. Most likely, the black text will have to be compressed a bit horizontally to match. That's a total of 2 drawings.
 
Vitaliy Kostrubko #:

Nicholas, hello!

I had a quick look through all this thread, but didn't find the answer to my question!

Could you please tell me HOW to make a normal "stroke" for text on the canvas?

(this mark is made on Canvas)

the whole point is that IF you make N copies of text and place it "in a circle" around the main text, then with a large font size (more than 50 points ... and I have ^ 150 points) and multi-line inscription, 5-7 lines (logs on the screen),
then when creating OBJECTS - the laptop can and hang ..... I had to restart the terminal ... and on kanvas - the laptop is quiet, but the time to create such a text multiline label = 5 minutes !!!!

...optimised the code, now on kanvas it creates 7 lines of log in 101 seconds (a little longer than a minute).

that's still a very long time !

Are there any ways or methods to create a faster text stroke?!

(I've seen this trick before - create a Canvas 1 time, and in it change sizes / pixels / colours ...) ... I'll try it, I'll report back later, ...
... but for now I'm still interested in the opinions of experts on this issue !

Thank you!

no way...wait for Blend2D to be integrated or use its DLL now. Hint: a font is a vector path. Draw it without filling it with a thick line, then overlay a normal image with a thin stroke and fill on top

 
Vitaliy Kostrubko #:

Nicholas, hello!

I had a quick look through all this thread, but didn't find the answer to my question!

Could you please tell me HOW to make a normal "stroke" for text on the canvas?

(this mark is made on Canvas)

the whole point is that IF you make N copies of text and place it "in a circle" around the main text, then with a large font size (more than 50 points ... and I have ^ 150 points) and multi-line inscription, 5-7 lines (logs on the screen),
then when creating OBJECTS - the laptop can and hang ..... I had to restart the terminal ... and on kanvas - the laptop is quiet, but the time to create such a text multiline label = 5 minutes !!!!

...optimised the code, now on kanvas it creates 7 lines of log for 101 seconds (a little longer than a minute).

that's still a very long time !

Are there any ways or methods to create a faster text stroke?!

(I've seen this trick before - create a Canvas once, and in it change sizes / pixels / colours ...) ... I'll try it, I'll report back later, ...
... but for now I'm still interested in the opinions of experts on this issue !

Thank you !

Hi!
101 sec - I don't understand why it takes so long. I think there is some symantic error in your code. 100-200 milliseconds - you can still believe it.
But on the other hand, font rendering is terribly slow, at least in MQL5. I checked it once and was shocked. It is 100 times slower than I expected. I even had an idea to write a library for fast font rendering and its smooth scaling. But I didn't find the motivation, as there are no such tasks where there is a lot of changing text.
In your case, the first thing that comes to mind is to simply find the necessary outline ttf font and importer it. I think this is the easiest solution.
for example:
https://ofont.ru/category/5


But if you need blurred edges, then probably the best way is to first put the desired text of one colour (e.g. black) in the canvas, blur it (any quality LLM can easily cope with this if you formulate a task for it, starting from the presence of a ready bitmap array bmp[w*h], in which you need to blur the image in the most efficient way and a given dispersion). And then in the same place to make a normal text of the same size, but of the opposite colour.
Well or as Max said, to wait until MQ will get software access to the possibilities of Blend2D. But this can take a terribly long time. ))

 
Nikolai Semko #:

But if you need blurred edges, then probably the best way is to first output the required text of one colour (e.g. black) into the canvas, blurit (any quality LLM caneasily cope with this if you formulate a task for it, starting from the presence of a ready bitmap array bmp[w*h], in which you need to blur the image in the most efficient way and a given dispersion). And then in the same place to make a normal text of the same size, but of the opposite colour.


Here I tried to ask claude.ai.
And what she answered me:
https://claude.ai/share/cad08fbb-2502-47bf-b99d-c325ee968609
in case the link will not open in Russia, then here is the code that was generated, but I did not check it. Check it yourself please:

//+------------------------------------------------------------------+
//| Gaussian Blur function for bitmap array |
//| bmp[] - ARGB pixel array (uint format: 0xAARRGGBB) |
//| width, height - image dimensions|
//| blur_dispersion - variance (sigma^2) for Gaussian kernel |
//+------------------------------------------------------------------+
void BlurBmp(uint &bmp[], int width, int height, double blur_dispersion)
{
   if(width <= 0 || height <= 0 || blur_dispersion <= 0.0)
      return;
   
   double sigma = MathSqrt(blur_dispersion);
   
   // Calculate kernel radius (3*sigma covers ~99.7% of distribution)
   int radius = (int)MathCeil(3.0 * sigma);
   if(radius < 1) radius = 1;
   
   int kernel_size = 2 * radius + 1;
   
   // Build 1D Gaussian kernel
   double kernel[];
   ArrayResize(kernel, kernel_size);
   
   double sum = 0.0;
   for(int i = 0; i < kernel_size; i++)
   {
      int x = i - radius;
      kernel[i] = MathExp(-(x * x) / (2.0 * blur_dispersion));
      sum += kernel[i];
   }
   
   // Normalize kernel
   for(int i = 0; i < kernel_size; i++)
      kernel[i] /= sum;
   
   // Temporary buffer
   uint temp[];
   ArrayResize(temp, ArraySize(bmp));
   ArrayCopy(temp, bmp);
   
   // Horizontal pass
   for(int y = 0; y < height; y++)
   {
      for(int x = 0; x < width; x++)
      {
         double r = 0.0, g = 0.0, b = 0.0, a = 0.0;
         
         for(int k = 0; k < kernel_size; k++)
         {
            int sample_x = x + k - radius;
            
            // Clamp to image bounds
            if(sample_x < 0) sample_x = 0;
            if(sample_x >= width) sample_x = width - 1;
            
            uint pixel = temp[y * width + sample_x];
            double weight = kernel[k];
            
            a += ((pixel >> 24) & 0xFF) * weight;
            r += ((pixel >> 16) & 0xFF) * weight;
            g += ((pixel >> 8) & 0xFF) * weight;
            b += (pixel & 0xFF) * weight;
         }
         
         bmp[y * width + x] = ((uint)a << 24) | ((uint)r << 16) | 
                               ((uint)g << 8) | (uint)b;
      }
   }
   
   // Copy for vertical pass
   ArrayCopy(temp, bmp);
   
   // Vertical pass
   for(int y = 0; y < height; y++)
   {
      for(int x = 0; x < width; x++)
      {
         double r = 0.0, g = 0.0, b = 0.0, a = 0.0;
         
         for(int k = 0; k < kernel_size; k++)
         {
            int sample_y = y + k - radius;
            
            // Clamp to image bounds
            if(sample_y < 0) sample_y = 0;
            if(sample_y >= height) sample_y = height - 1;
            
            uint pixel = temp[sample_y * width + x];
            double weight = kernel[k];
            
            a += ((pixel >> 24) & 0xFF) * weight;
            r += ((pixel >> 16) & 0xFF) * weight;
            g += ((pixel >> 8) & 0xFF) * weight;
            b += (pixel & 0xFF) * weight;
         }
         
         bmp[y * width + x] = ((uint)a << 24) | ((uint)r << 16) | 
                               ((uint)g << 8) | (uint)b;
      }
   }
}


MQL5 image blur function
  • claude.ai
Shared via Claude, an AI assistant from Anthropic
 
Nikolai Semko #:

here I tried to ask claude.ai.
And what she answered me:
https://claude.ai/share/cad08fbb-2502-47bf-b99d-c325ee968609
in case the link will not open in Russia, then here is the code that was generated, but I did not check it. Check it yourself please:


oops, I forgot to emphasise in the assignment that the blur should be through alpha channel so that there would be no artefacts when overlapping with another image.
here is its corrected version through alpha channel(transparency)
void BlurBmp(uint &bmp[], int width, int height, double blur_dispersion)
{
   if(width <= 0 || height <= 0 || blur_dispersion <= 0.0)
      return;
   
   double sigma = MathSqrt(blur_dispersion);
   int radius = (int)MathCeil(3.0 * sigma);
   if(radius < 1) radius = 1;
   
   int kernel_size = 2 * radius + 1;
   
   double kernel[];
   ArrayResize(kernel, kernel_size);
   
   double sum = 0.0;
   for(int i = 0; i < kernel_size; i++)
   {
      int x = i - radius;
      kernel[i] = MathExp(-(x * x) / (2.0 * blur_dispersion));
      sum += kernel[i];
   }
   
   for(int i = 0; i < kernel_size; i++)
      kernel[i] /= sum;
   
   uint temp[];
   ArrayResize(temp, ArraySize(bmp));
   ArrayCopy(temp, bmp);
   
   // Horizontal pass with alpha weighting
   for(int y = 0; y < height; y++)
   {
      for(int x = 0; x < width; x++)
      {
         double r = 0.0, g = 0.0, b = 0.0, a = 0.0;
         double weight_sum = 0.0;
         
         for(int k = 0; k < kernel_size; k++)
         {
            int sample_x = x + k - radius;
            if(sample_x < 0) sample_x = 0;
            if(sample_x >= width) sample_x = width - 1;
            
            uint pixel = temp[y * width + sample_x];
            double kernel_weight = kernel[k];
            double alpha = ((pixel >> 24) & 0xFF) / 255.0;
            
            // Combined weight: kernel * alpha
            double total_weight = kernel_weight * alpha;
            
            r += ((pixel >> 16) & 0xFF) * total_weight;
            g += ((pixel >> 8) & 0xFF) * total_weight;
            b += (pixel & 0xFF) * total_weight;
            a += alpha * kernel_weight;
            
            weight_sum += total_weight;
         }
         
         // Normalize by accumulated weight
         if(weight_sum > 0.0001)
         {
            r /= weight_sum;
            g /= weight_sum;
            b /= weight_sum;
         }
         
         bmp[y * width + x] = ((uint)(a * 255.0) << 24) | 
                              ((uint)r << 16) | 
                              ((uint)g << 8) | 
                              (uint)b;
      }
   }
   
   ArrayCopy(temp, bmp);
   
   // Vertical pass with alpha weighting
   for(int y = 0; y < height; y++)
   {
      for(int x = 0; x < width; x++)
      {
         double r = 0.0, g = 0.0, b = 0.0, a = 0.0;
         double weight_sum = 0.0;
         
         for(int k = 0; k < kernel_size; k++)
         {
            int sample_y = y + k - radius;
            if(sample_y < 0) sample_y = 0;
            if(sample_y >= height) sample_y = height - 1;
            
            uint pixel = temp[sample_y * width + x];
            double kernel_weight = kernel[k];
            double alpha = ((pixel >> 24) & 0xFF) / 255.0;
            
            double total_weight = kernel_weight * alpha;
            
            r += ((pixel >> 16) & 0xFF) * total_weight;
            g += ((pixel >> 8) & 0xFF) * total_weight;
            b += (pixel & 0xFF) * total_weight;
            a += alpha * kernel_weight;
            
            weight_sum += total_weight;
         }
         
         if(weight_sum > 0.0001)
         {
            r /= weight_sum;
            g /= weight_sum;
            b /= weight_sum;
         }
         
         bmp[y * width + x] = ((uint)(a * 255.0) << 24) | 
                              ((uint)r << 16) | 
                              ((uint)g << 8) | 
                              (uint)b;
      }
   }
}
 

Forum on trading, automated trading systems and testing trading strategies

Canvas is cool!

Nikolai Semko, 2025.11.18 16:40

   uint temp[];
   ArrayResize(temp, ArraySize(bmp));
   ArrayCopy(temp, bmp);

A redundant line, but impressive!


OFFTOP.

I wonder what fast (criterion below) algorithm would be suggested for tick compression: bid/ask/time_msc?

Forum on trading, automated trading systems and testing trading strategies.

Libraries: MathTicker - tick generator in mathematical mode

Forester, 2025.11.17 09:36 pm.

// Returns the size of the array in bytes.
template <typename T>
ulong GetSize( const T &Array[] ) { return((ulong)sizeof(T) * ArraySize(Array)); }

template <typename T1, typename T2>
double Criterion( const T1 &Decompression[], const T2 &Compression[], const ulong Interval )
{
  const double Performance = (double)ArraySize(Decompression) / Interval;

  return(Performance * ((double)GetSize(Decompression) / GetSize(Compression)));
}

At the link the current record holder for decompression (much more demanded), created by man.

 
fxsaber #:

A superfluous line, but impressive!


OFFTOP.

I wonder what fast (criterion below) algorithm would be suggested for tick compression: bid/ask/time_msc?

At the link, the current record holder for decompression (much more demanded) is man-made.

Yes, quite interesting and useful. Thanks. Will only be able to go into more detail in a month. Time is a real problem at the moment.