News:

Masm32 SDK description, downloads and other helpful links
Message to All Guests

Main Menu

Rainbow text with GdipDrawString issue

Started by guga, November 24, 2020, 04:36:09 PM

Previous topic - Next topic

guga

Hi Guys, i succeeded to use gdiplus to draw a rainbow text on a window/control DC but i´m failing to try to understand why is it working:

The resultant effect is this:



Which is the same as

Taken at: https://stackoverrun.com/ru/q/1858879


Also there are some good examples made by Mikl here (But, it is for 64 bits and not 32):

https://board.flatassembler.net/topic.php?p=205372
https://board.flatassembler.net/topic.php?p=205373

and

https://wasm.in/threads/rectf-pointf-kak-realizovat.32727

On wasm forum the example05.zip is like this:


But it is not working and also is in 64Bits, instead 32   :sad:

Also. Mikl seem to do an outline text, but how to do it ? I mean, to display something like:


MY version i s working, but i´m failing to understand why.

What i did so far was:

; Variables and macros used:

[Pointf:
Pointf.X: F$ 10.0;.0
Pointf.Y: F$ 100.0;.0
Pointf.W: F$ 0 ; ??? What is this ???
Pointf.H: F$ 0] ; ??? What is this ???

; Macro GDIP_ARGB
[GDIP_ARGB | (#4 or (#3 shl 8) or (#2 shl 16) or (#1 shl 24))]



;;
     hSrcDC(in) - The DC of teh window/control where the text should appear
     pFontName(in) - Point a Ansi Null Terminated String representing the font name
     pText(in) - Point a Ansi Null Terminated String representing the Text to be placed onto the DC
;;

Proc GdiTextPaint:
    Arguments @hSrcDC, @pFontName, @pText
    Local @pGraphics, @pFontFamily, @hStatus, @pFont, @pBlackBrush, @nativeFormat, @FontSize, @hGdiPlusStringFormat
    Structure @FontNameWDis (&MAX_PATH*2)
    Uses ecx, edx, edi

    finit
    mov D@FontSize 24
    lea eax D@FontSize
    fild D@FontSize | fstp F@FontSize

    call 'Rosmem.ZeroMemory' D@FontNameWDis, (&MAX_PATH*2) ; Clean up the Variable used for the font name

    lea eax D@pGraphics
    call 'gdiplus.GdipCreateFromHDC' D@hSrcDC, eax
    mov D@hStatus eax

    call 'kernel32.MultiByteToWideChar' &CP_ACP, 0, D@pFontName, 0-1, D@FontNameWDis, (&MAX_PATH-1)
   
    ; quality mode
    call 'gdiplus.GdipSetTextRenderingHint' D@pGraphics, TEXTRENDERINGHINT_ANTIALIAS

    ;  Create the font
    lea eax D@pFontFamily
    call 'gdiplus.GdipCreateFontFamilyFromName' D@FontNameWDis, &NULL, eax
    If_And eax = &S_OK, D@pFontFamily <> 0
        lea eax D@pFont
        call 'gdiplus.GdipCreateFont' D@pFontFamily, D@FontSize, (GDIP_FONT_STYLE_ITALIC+GDIP_FONT_STYLE_UNDERLINE), GDIP_UNIT_POINT, eax
        call 'gdiplus.GdipDeleteFontFamily' D@pFontFamily
    End_If

    ; create a gradient text
    lea eax D@pBlackBrush
    call GdipCreateGradientbrush 10, 100, 100, 100, {GDIP_ARGB 255, 255, 0, 0}, {GDIP_ARGB 255, 255, 255, 0}, eax
;;
    ; Create a solid brush . Ok to do without the rainbow effect.
    lea eax D@pBlackBrush
    call 'gdiplus.GdipCreateSolidFill' {GDIP_ARGB 255, 0, 0, 190}, eax
;;

    ; Draw the string
    call 'RosMem.FastZeroMem' D@FontNameWDis, (&MAX_PATH*2)
    call 'kernel32.MultiByteToWideChar' &CP_ACP, 0, D@pText, 0-1, D@FontNameWDis, (&MAX_PATH-1)


    ; format the string
    lea eax D@hGdiPlusStringFormat
    call 'gdiplus.GdipCreateStringFormat' 0 , &LANG_NEUTRAL, eax
    call 'gdiplus.GdipSetStringFormatAlign' D@hGdiPlusStringFormat, GDIPLUS_STRINGALIGNMENT_NEAR;GDIPLUS_STRINGALIGNMENT_CENTER
    call 'GDIPLUS.GdipSetStringFormatLineAlign' D@hGdiPlusStringFormat, GDIPLUS_STRINGALIGNMENT_NEAR;GDIPLUS_STRINGALIGNMENT_CENTER

    ; Draw the string
    call 'gdiplus.GdipDrawString' D@pGraphics, D@FontNameWDis, 0-1, D@pFont, Pointf, D@hGdiPlusStringFormat, D@pBlackBrush

    ; Cleanup
    If D@pFont <> 0
        call 'gdiplus.GdipDeleteFont' D@pFont
    End_If

    If D@pBlackBrush <> 0
        call 'gdiplus.GdipDeleteBrush' D@pBlackBrush
    End_If

    If D@pGraphics <> 0
        call 'gdiplus.GdipDeleteGraphics' D@pGraphics
    End_If

EndP


; GdipCreateGradientbrush is the main function responsible to create the gradient text effect



[RECT.leftDis 0
RECT.topDis 4
RECT.rightDis 8
RECT.bottomDis 12]

; LineGradient Mode
[LINEAR_GRADIENTMODE_HORIZONTAL 0
LINEAR_GRADIENTMODE_VERTICAL 1
LINEAR_GRADIENTMODE_FORWARDDIAGONAL 2
LINEAR_GRADIENTMODE_BACKWARDDIAGONAL 3]

; WarpMode constants
[WARPMODE_PERSPECTIVE 0
WARPMODE_BILINEAR 1]

Proc GdipCreateGradientbrush:
    Arguments @XPos, @YPos, @Width, @Height, @Color1, @Color2, @lineGradient
    Structure @RECT 16, @RECT.leftDis 0,  @RECT.topDis 4,  @RECT.rightDis 8,  @RECT.bottomDis 12
    Uses ecx, edx

    mov ecx D@RECT
    mov eax D@XPos | mov D$ecx+RECT.leftDis eax
    mov eax D@YPos | mov D$ecx+RECT.topDis eax
    mov eax D@Width | mov D$ecx+RECT.rightDis eax
    mov eax D@Height | mov D$ecx+RECT.bottomDis eax
    call 'gdiplus.GdipCreateLineBrushFromRectI' D@RECT, D@Color1, D@Color2, LINEAR_GRADIENTMODE_HORIZONTAL, WARPMODE_PERSPECTIVE, D@lineGradient

EndP


Example of usage:

; the following function can be placed in WM_PAINT message

    call GdiTextPaint D@hMemDC, {B$ "Arial", 0}, {B$ "Hello World!", 0} ; must be placed before the bitblt to avoid flicker
    call 'GDI32.BitBlt' D@hDC, 0, 0, D@Width, D@Height, D@hMemDC, 0, 0, &SRCCOPY



At GdipCreateGradientbrush what is being passed onto GdipCreateLineBrushFromRectI ??? I mean, the X, YPos seems to be the same ones as used in Pointf structure from GdipDrawString but....what are the width and height from this structure? Should it be always set to 0 ???

Also....what are the Width and Height in GdipCreateLineBrushFromRectI ? Are they the width/height of the whole control/window dc or it can be any aleatory value ? On this example, i only succeeded to make it work setting Width = 100 Height = 100 and keeping X = 10, Y = 100

Note:
Btw...The goal (once it is fixed) is try to port the below to masm/RosAsm etc to we do things like these:





As described in: https://www.codeproject.com/Articles/42529/Outline-Text
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

guga

Btw....

Another question

How do i get the width and height of the text and limit it to a certain area ?

Say i want he text to wrap inside the width of the control, how to determine the maximum width of the text and how to recalculate the height ?

Like this:

Say, i have a dc from a window/control measuring

Width = 100
Height = 100

And my text is "Hello world, i´m typing this text to calculate the full length of this". Now let´s say that this text extrapolates the maximum width of 100. At the end it will need to be displayed as:

"Hello world, i´m typing this text to calculate <-----Reached limit of 100 width
the full length of this" <--- But what is the new height ????
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

fearless

Using gradient brushes for the text should give a rainbow effect, i guess the direction of the gradient will determine how it appears, plus also maybe the size of the brush pattern - if it repeats it might look odd, or if it stretches the gradient to fit text it might look weird.
I think using paths (GraphicPath) is the way to achieve the outline effect.In gdi you can use DT_CALCRECT flag in DrawText to calc the area needed for text wrapping. In Gdi+ I guess there will be something similar

guga

Quote from: fearless on November 25, 2020, 12:00:07 AM
Using gradient brushes for the text should give a rainbow effect, i guess the direction of the gradient will determine how it appears, plus also maybe the size of the brush pattern - if it repeats it might look odd, or if it stretches the gradient to fit text it might look weird.
I think using paths (GraphicPath) is the way to achieve the outline effect.In gdi you can use DT_CALCRECT flag in DrawText to calc the area needed for text wrapping. In Gdi+ I guess there will be something similar

In Gdi+, the direction is given from the GdipCreateLineBrushFromRectI function using these equates as the 4th parameeter
; LineGradient Mode
[LINEAR_GRADIENTMODE_HORIZONTAL 0
LINEAR_GRADIENTMODE_VERTICAL 1
LINEAR_GRADIENTMODE_FORWARDDIAGONAL 2
LINEAR_GRADIENTMODE_BACKWARDDIAGONAL 3]

About using DrawText +  DT_CALCRECT , maybe works using gdipmeasurestring ?
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

avcaballero

Some time ago, I did this text effect: text with dynamic plasma. Pure and brute GDI  :thumbsup:

guga

Quote from: caballero on November 25, 2020, 09:08:18 PM
Some time ago, I did this text effect: text with dynamic plasma. Pure and brute GDI  :thumbsup:

Great work, caballero. Thank you. I´l take a look at the code.

One thing....I saw you seems to use the text as a mask, right ? But... couldnt´it also use the generated images as a texture for the font to be used as a brush with Gdi+ ?

I mean, i´m currently fixing some functions to use Gdi+ to do effects in text and maybe use a texture over the gdi+ text itself, but don´t know if it is possible to do yet.
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

avcaballero

If I'm not wrong it could be done in GDI:
http://abreojosensamblador.epizy.com/?Tarea=6&SubTarea=6#VariasGDIEjemplo

See the last example: PintarWC07e

And also with GDI+
http://abreojosensamblador.epizy.com/?Tarea=6&SubTarea=6#GDIPElipses

guga

#7
Thank you a lot, caballero, i´ll take a look at the code.


Today i succeeded to create the outline effect as described here: https://www.codeproject.com/Articles/42529/Outline-Text

But i´m having a small problem with the rectangle that encloses the text, since it´s not being attached to the bottom of the text as below





    ;  Draw the rectangle that encloses the text.
    If D$edi+GdipTextNfo.ShowTextRectDis <> &FALSE ; Check the flag responsible enable/disable the rectangle
        ; The rectangle area must be in float, because it is the same to be used in GdipDrawString
        fld1 | fstp F@PenTextRectWidth
        lea eax D@pPen
        call 'gdiplus.GdipCreatePen1' D$edi+GdipTextNfo.FontColorDis, F@PenTextRectWidth, GDIP_UNIT_PIXEL, eax
        call 'gdiplus.GdipDrawRectangle' D@pGraphics, D@pPen, F@BoundingBox.XDis, F@BoundingBox.YDis, F@BoundingBox.WidthDis, F@BoundingBox.HeightDis
    End_If



But...without the text effect the rectangle is ok




I´ll try to fix that. I don´t know if i need to set the rectangle routine before the text effect or is something in the text effect itself that is ruining the height

I´m writing all the code in separated parts to avoid any gdi leaking. So, we can have an isolate function to work only with the background DC color, other that works only for the loaded images and other for the text


Edited:

Fixed it.. This is the current behaviour of the tests i´m doing

https://streamable.com/95oh2w
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

daydreamer

Quote from: guga on November 28, 2020, 08:50:14 AM
Thank you a lot, caballero, i´ll take a look at the code.


Today i succeeded to create the outline effect as described here: https://www.codeproject.com/Articles/42529/Outline-Text

But i´m having a small problem with the rectangle that encloses the text, since it´s not being attached to the bottom of the text as below





    ;  Draw the rectangle that encloses the text.
    If D$edi+GdipTextNfo.ShowTextRectDis <> &FALSE ; Check the flag responsible enable/disable the rectangle
        ; The rectangle area must be in float, because it is the same to be used in GdipDrawString
        fld1 | fstp F@PenTextRectWidth
        lea eax D@pPen
        call 'gdiplus.GdipCreatePen1' D$edi+GdipTextNfo.FontColorDis, F@PenTextRectWidth, GDIP_UNIT_PIXEL, eax
        call 'gdiplus.GdipDrawRectangle' D@pGraphics, D@pPen, F@BoundingBox.XDis, F@BoundingBox.YDis, F@BoundingBox.WidthDis, F@BoundingBox.HeightDis
    End_If



But...without the text effect the rectangle is ok




I´ll try to fix that. I don´t know if i need to set the rectangle routine before the text effect or is something in the text effect itself that is ruining the height

I´m writing all the code in separated parts to avoid any gdi leaking. So, we can have an isolate function to work only with the background DC color, other that works only for the loaded images and other for the text


Edited:

Fixed it.. This is the current behaviour of the tests i´m doing

https://streamable.com/95oh2w
I worked much with button controls used them for texts instead of GDI drawing text,there are customdraw on windows controls too,what about a text control to use for text(LABEL) instead of mess with GDI+?
instead of drawtext,its invoke sendmessage,hwndbutton,WM_SETTEXT,NULL,ADDR text
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

guga

Quote from: daydreamer on November 29, 2020, 12:04:32 AM
I worked much with button controls used them for texts instead of GDI drawing text,there are customdraw on windows controls too,what about a text control to use for text(LABEL) instead of mess with GDI+?
instead of drawtext,its invoke sendmessage,hwndbutton,WM_SETTEXT,NULL,ADDR text

Hi Daydreamer. Using customdraw could be an alternative for controls, but i´m not there yet. I´m not sure i understood what you told about using text control...you mean the lables inside controls is that it ? If is that so, perhaps it works with customdraw, but it will require more functions that are needed i suppose.

The problem of using customdraw is that i´ll need to create several functions to place in different parts of the code, rather then 1 or two only to be used in certain windows messages such as WM_CREATE, WM_INITDIALOG and WM_PAINT. I´m trying to do it in a sort of a dll library where we can have full control on what´s being done with less effort as possible.


I'm trying to lean a bit of the gdiplus apis, in order to create alternatives ways of adding some effects to windows (or even a image editor app) The goal is to create less functions as possible that enables to control everything. For example, to display images onto a DC (from a window or a control) without leaking, all is needed is 1 single function to setup a structure to be used on another function that needs to be located in WM_PAINT message. The same goes for Texts. Gdi+ can handle multiline texts too.

So, basically at the end we are using only 2 functions. 1 in WM_CREATE (or WM_INITDIALOG) and other in the main painting message WM_PAINT

Take a look at this other test i made using a gif animated as the background of a text: https://streamable.com/e4mhcp   :smiley: :smiley:

Add those effects to text using gdi plus can be done with GdipDrawPath followed by GdipFillPath. For what i saw so far, there´s no leakings
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

daydreamer

great project :thumbsup:
any kind of animation,TIMER proc sending update screen combined with PAINT proc vs TIMER proc using GetDC/rasterize code/releaseDC instead maybe worth trying whats better?

cool video editor adding japanese subtext caps or whatever subtext you like could be end result,also have interest in anime/learning foreign languages,double subtext japanese/english  helps alot understanding what is said reading English subtext,while testing/exercise japanese skill reading Japanese subtext
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding

guga

Quote from: daydreamer on November 29, 2020, 08:47:16 AM
great project :thumbsup:
any kind of animation,TIMER proc sending update screen combined with PAINT proc vs TIMER proc using GetDC/rasterize code/releaseDC instead maybe worth trying whats better?

cool video editor adding japanese subtext caps or whatever subtext you like could be end result,also have interest in anime/learning foreign languages,double subtext japanese/english  helps alot understanding what is said reading English subtext,while testing/exercise japanese skill reading Japanese subtext

Hi Daydreamer

Many tks :thumbsup: :thumbsup:

The animaton is done only once without any timerproc involved. I created a function called SetAnimationInterval, which calculates the amount of time (in ms) to be passed onto WM_TIMER message from a given Frame Rate (29.970, 25, 50, 60 or whatever other is needed). It converts FPS (Frame Rate) to miliseconds and use SetTimer to create the proper timer id (without the needs of any timerproc callback routine). This part of the code is done as:


Proc SetAnimationInterval:
    Arguments @hWnd, @IdEvent, @pFrameRate, @KeyFrame
    Local @Seconds
    Uses ecx, edx

    finit

    mov D@Seconds 1000
    mov eax D@pFrameRate
    fild D@Seconds | fdiv F$eax
    mov eax D@KeyFrame | On eax = 0, mov eax 1
    mov D@Seconds eax | fimul F@Seconds
    lea eax D@Seconds
    fistp D$eax
    mov eax D$eax
    On eax < &USER_TIMER_MINIMUM, mov eax &USER_TIMER_MINIMUM
    On eax > &USER_TIMER_MAXIMUM, mov eax &USER_TIMER_MAXIMUM
    mov D@Seconds eax
    call 'user32.SetTimer' D@hWnd, D@IdEvent, eax, 0
    mov eax D@Seconds

EndP


The above function is used internally on a single function i made to work with whatever images you need (I named it as: GdipCreateImageInfo api) . All it is needed is feed a proper structure used on this Api and place it in WM_CREATE or WM_INITDIALOG. And the to adjust the frames all is necessary is setup the current frame in WM_TIMER as:


    ...Else_If D@Message = &WM_TIMER

        call 'USER32.InvalidateRect' D@Addressee, 0, 0 ; <--- Just to clean up the screen if needed
        If D$GdipImageNfo1.TotalFrames > 1 ; ------> A member of the structure "GdipImageNfo" used in GdipCreateImageInfo. If the image have more then 1 frame (Animated gif or tiff), it wil increment the counter to use the next frame inside WM_PAINT
            inc D$GdipImageNfo1.CurFramePos ; Update the current frame position
        End_If
        If D$GdipImageNfo2.TotalFrames > 1
            inc D$GdipImageNfo2.CurFramePos
        End_If



On it´s turn, to get the next frame it is also done with one single api i labeled as: "GdipImgPaint". Inside this api it will locate the TotalFrames member of the structure GdipImageNfo and will point to the next frame, without needing to do a lot of calculations. This function is as:


Proc GdipImgPaint::
    Arguments @hDC, @pGdiImgNfo
    Local @pGraphics, @CurXPos, @CurYPos, @ImgWidth, @ImgHeight, @ImgRatio, @Return
    Uses ecx, edx, edi

    lea eax D@pGraphics
    call 'gdiplus.GdipCreateFromHDC' D@hDC, eax
    On eax <> &S_OK, ExitP

    mov edi D@pGdiImgNfo

    mov eax D$edi+GdipImageNfo.TotalFramesDis ; <------------------- get the next frame oif we are dealing with animated gif or tiff.  The frame is updated  in WM_TIMER
    .If eax > 1
        If D$edi+GdipImageNfo.CurFramePosDis => eax
            mov D$edi+GdipImageNfo.CurFramePosDis 0
        End_If
        call 'gdiplus.GdipImageSelectActiveFrame' D$edi+GdipImageNfo.pGdiImageDis, FRAME_DIMENSION_TIME, D$edi+GdipImageNfo.CurFramePosDis
        If eax <> &S_OK
            mov D@Return eax
            call 'gdiplus.GdipDeleteGraphics' D@pGraphics
            mov eax D@Return
            ExitP
        End_If
    .End_If

    mov eax D$edi+GdipImageNfo.ImgXPosDis | mov D@CurXPos eax
    mov eax D$edi+GdipImageNfo.ImgYPosDis | mov D@CurYPos eax
    mov eax D$edi+GdipImageNfo.DisplayTypeDis
    .If eax = GDIP_DRAWIMG_DEFAULT
        mov eax D$edi+GdipImageNfo.ImgWidthDis | mov D@ImgWidth eax
        mov eax D$edi+GdipImageNfo.ImgHeightDis | mov D@ImgHeight eax
    .Else_If eax = GDIP_DRAWIMG_FILL
        mov D@CurXPos 0
        mov D@CurYPos 0
        mov eax D$edi+GdipImageNfo.CtrlWidthDis | mov D@ImgWidth eax
        mov eax D$edi+GdipImageNfo.CtrlHeightDis | mov D@ImgHeight eax
    .Else_If eax = GDIP_DRAWIMG_AUTO_FILL_HORZ
        mov D@CurXPos 0
        mov eax D$edi+GdipImageNfo.CtrlWidthDis | mov D@ImgWidth eax
        mov eax D$edi+GdipImageNfo.ImgHeightDis | mov D@ImgHeight eax
    .Else_If eax = GDIP_DRAWIMG_AUTO_FILL_VERT
        mov D@CurYPos 0
        mov eax D$edi+GdipImageNfo.CtrlHeightDis | mov D@ImgHeight eax
        mov eax D$edi+GdipImageNfo.ImgWidthDis | mov D@ImgWidth eax

    .Else_If eax = GDIP_DRAWIMG_AUTO_VERT
        mov D@CurYPos 0
        mov eax D$edi+GdipImageNfo.CtrlHeightDis | mov D@ImgHeight eax
        ; Ratio = ImgWidth/ImgHeight
        ; New width = Ratio*CtrlHeight
        lea eax D@ImgWidth;@ImgRatio
        ;fild F$edi+GdipImageNfo.ImgWidthDis | fidiv F$edi+GdipImageNfo.ImgHeightDis | fimul F$edi+GdipImageNfo.CtrlWidthDis | fistp F$eax
        fild F$edi+GdipImageNfo.CtrlWidthDis | fidiv F$edi+GdipImageNfo.CtrlHeightDis | fimul F$edi+GdipImageNfo.ImgWidthDis | fistp F$eax
    .Else_If eax = GDIP_DRAWIMG_AUTO_HORZ
        mov D@CurXPos 0
        mov eax D$edi+GdipImageNfo.CtrlWidthDis | mov D@ImgWidth eax
        lea eax D@ImgHeight
        fild F$edi+GdipImageNfo.CtrlHeightDis | fidiv F$edi+GdipImageNfo.CtrlWidthDis | fimul F$edi+GdipImageNfo.ImgHeightDis | fistp F$eax

    .Else
        mov eax D$edi+GdipImageNfo.CtrlWidthDis | mov D@ImgWidth eax
        mov eax D$edi+GdipImageNfo.CtrlHeightDis | mov D@ImgHeight eax
    .End_If

    call 'gdiplus.GdipDrawImageRectI' D@pGraphics, D$edi+GdipImageNfo.pGdiImageDis, D@CurXPos, D@CurYPos, D@ImgWidth, D@ImgHeight
    If eax <> &S_OK
        mov D@Return eax
        call 'gdiplus.GdipDeleteGraphics' D@pGraphics
        mov eax D@Return
    Else
        call 'gdiplus.GdipDeleteGraphics' D@pGraphics
    End_If

EndP


The above function is used inside WM_PAINT. Currently on this preliminary tests, i´m using 3 main Apis to work with images and text passing them through WM_PAINT such as:


___________________________________________________________________________

(...)
    ...Else_If D@Message = &WM_PAINT

        call On_WmPaintIconRsrc D@Addressee
(...)
___________________________________________________________________________

Proc On_WmPaintIconRsrc:
    Arguments @Adressee
    Local @hDC
    Structure @PAINTSTRUCT 64, @PAINTSTRUCT.hdcDis 0
    Uses ecx, edx, edi

    call 'User32.BeginPaint' D@Adressee, D@PAINTSTRUCT
    mov D@hDC eax

    call GdipImageDraw D@Adressee, D@hDC

    call 'USER32.EndPaint' D@Adressee, D@PAINTSTRUCT

EndP
___________________________________________________________________________

Proc GdipImageDraw:
    Arguments @Adressee, @hDC
    Local @ctx, @hMemDC, @hbr, @Width, @Height, @XPos, @YPos
    Structure @RECT 16, @RECT.leftDis 0, @RECT.topDis 4, @RECT.rightDis 8, @RECT.bottomDis 12
    Uses ecx, edx, edi

    call 'GDI32.SaveDC' D@hDC | mov D@ctx eax

    lea eax D@Width
    lea ecx D@Height
    call 'FastCRT.CreateWorkingDC' D@Adressee, eax, ecx, {RGB 47 47 47}
    mov D@hMemDC eax

    mov D@XPos 0
    mov D@YPos 0

    call 'FastCRT.GdipImgPaint' D@hMemDC, GdipImageNfo2
    call 'FastCRT.GdipImgPaint' D@hMemDC, GdipImageNfo1

     ; must be placed before the bitblt to avoid flicker
    call GdiTextPaint D@hMemDC, GdipTextNfo1

    call 'GDI32.BitBlt' D@hDC, 0, 0, D@Width, D@Height, D@hMemDC, 0, 0, &SRCCOPY

    call 'GDI32.DeleteDC' D@hMemDC
    call 'GDI32.RestoreDC' D@hDC, D@ctx

EndP
___________________________________________________________________________



Once i succeed to fix this text function, i´ll try to create one single GdipImageDraw function to use as a dll for everything (Images texts and effects). Maybe labeling it as: GdipImageDrawEx or something. So i can use it simple as:


Proc On_WmPaintIconRsrc:
    Arguments @Adressee;, @pFile, @Filesize
    Local @hDC
    Structure @PAINTSTRUCT 64, @PAINTSTRUCT.hdcDis 0
    Uses ecx, edx, edi

    call 'User32.BeginPaint' D@Adressee, D@PAINTSTRUCT
    mov D@hDC eax

    call 'FastCRT.GdipImageDrawEx' D@Adressee, D@hDC ; <------ This is what i plan to do. So, 1 single function/api to handle everything related to the DC of a window/control. So, we can paint, use imahges, texts etc.
                                                                                         ;             Simply setting it up in WM_CREATE and pass the main function here only once. On this case the api is built for a dll  i called "FastCRT" that conains lots of general usage functions.

    call 'USER32.EndPaint' D@Adressee, D@PAINTSTRUCT

EndP



All of these could be useful for all on our daily needs. I´m doing this dll for general RosAsm usage, but it could also be used for masm as well...and...JJ may also like it, since he also uses GdiPlus in his projects and in masmbasic as well :azn: :azn: :azn:
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

HSE

Equations in Assembly: SmplMath

guga

"cool video editor adding japanese subtext caps or whatever subtext you like could be end result,also have interest in anime/learning foreign languages,double subtext japanese/english  helps alot understanding what is said reading English subtext,while testing/exercise japanese skill reading Japanese subtext"

I forgot answering this.  Very good idea, indeed. This was what motivated the guy at codeproject from where i´m biasing these functions. The main problem is that i don´t know how to write things in japanese or other Unicode Data. I mean, i would need to know the Hexadecimal values of some text written in japanese so i could be able to test the routine. Can you post the hexadecimal values of a japanese string so i can try testing it ?

Quote from: HSE on November 29, 2020, 09:32:14 AM
Impressive  :thumbsup:

Tks a lot, HSE. :thumbsup: :thumbsup:

I´m fixing this to see the better way to handle those texts. Currently the GdiTextPaint function converts a Ansi String to Unicode (needed for gdi+ apis) and allocated and deallocated the memory used in Unicode strings. When we are dealing with a still image (such as jpg, bmp, png etc) there´s no problem in terms of speed or performance from those alloc/deallocs.  But, when we are dealing with animated gif/tiff, it certainly slows down a bit due to the internal allocation/deallocation routines.

So, i´m thinking what could be better to do. If i allow the conversion and allocation of the necessary buffer once in WM_CREATE/WM_INITDIALOG and let to the user deallocate the memory when it is no longer needed or i let it as the way it is already. I´l give a try later to see how it works in terms of speed in animation gifs to decide either i remove those alloc/deallocs in WM_PAINT or not.
Coding in Assembly requires a mix of:
80% of brain, passion, intuition, creativity
10% of programming skills
10% of alcoholic levels in your blood.

My Code Sites:
http://rosasm.freeforums.org
http://winasm.tripod.com

daydreamer

Guga, might need download language pack to show correctly
Just easy to test character sets,ascii A = 041h,use 16bit unicode and 03041h start hiragana, 030a1h start katakana,
Cjk character set starts about 04100h
For display testing purposes it's only to add 03000h, 04100h to a ascii test string
my none asm creations
https://masm32.com/board/index.php?topic=6937.msg74303#msg74303
I am an Invoker
"An Invoker is a mage who specializes in the manipulation of raw and elemental energies."
Like SIMD coding