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

Gdip_TextToGraphics vertical alignment #17

Open
mmikeww opened this issue May 23, 2018 · 10 comments
Open

Gdip_TextToGraphics vertical alignment #17

mmikeww opened this issue May 23, 2018 · 10 comments

Comments

@mmikeww
Copy link
Owner

mmikeww commented May 23, 2018

from:
https://autohotkey.com/boards/viewtopic.php?p=219472#p219472

Here is the definition of Gdip_TextToGraphics

Gdip_TextToGraphics(pGraphics, Text, Options, Font:="Arial", Width:="", Height:="", Measure:=0)
{

In the comments of Example 8, tic says:

; As mentioned previously, you don not need to specify the last 2 parameters, the width and height, unless
; you are planning on using the p option with the x,y,w,h to use the percentage

But, the forum post reports that the vertical alignment options "vCenter|Top|Bottom" will fail if no Height param is passed. If we change Example 8 to this:

Options := "vCenter cbbffffff"
Gdip_TextToGraphics(G, "Tutorial 8`n`nThank you for trying this example", Options, Font)

the function will fail because the default values of Width/Height are empty strings "" which we cannot perform math with.

@mmikeww
Copy link
Owner Author

mmikeww commented May 23, 2018

There are multiple issues with this vertical alignment option:

1

It is impossible to calculate the vCenter or Bottom positioning without knowing the full height of the bitmap. So I think that needs to be checked for, and an error thrown if not.

2

The vCenter and Bottom calculations use the existing Height variable, but that can be modified and passed through in the options. I believe it should be using the original IHeight. Try using this for Example 8:

Options := "Bottom h50 cbbffffff"
Gdip_TextToGraphics(G, "Tutorial 8`n`nThank you for trying this example", Options, Font, Width, Height)

Above, we specify both Bottom and h50, but the text does NOT get drawn on the bottom. If we change Height to IHeight below in the TextToGraphics, it behaves correctly:

		else if (vPos[0] = "Bottom") || (vPos[0] = "Down")
			ypos := IHeight-ReturnRC[4]

This should be changed for vPos="vCenter" too

3

vPos="vCenter" should not increment ypos

Try this for Example 8:

Options := "vCenter y50 cbbffffff"
Gdip_TextToGraphics(G, "Tutorial 8`n`nThank you for trying this example", Options, Font, Width, Height)

Here we have both vCenter and y50, and the text gets drawn at the vertical center +50 pixels lower. The vertical alignment should override any y-option, like it already does for Top and Bottom. And so we would just need to change the += to :=

mmikeww added a commit that referenced this issue May 23, 2018
Issue #17
@mmikeww
Copy link
Owner Author

mmikeww commented May 23, 2018

you are wrong. I said that it will fail because of Width and height are nowhere declared properly (it is not a number) if i omit them

Yes I said that in the top post here, that it is an empty string "" and therefore we cannot perform math since it is not a number

and also equation for Bottom|Down case is wrong (it should be "+=" instead of ":=")

I argue against this. I think Bottom should always be the bottom of the bitmap, as that was what was originally intended in the function by the author. He also did the same for Top, also making it absolute and overriding any y option. The confusion arises with vCenter, but I argue for that in point # 3 above

@smarq8
Copy link

smarq8 commented May 23, 2018

I do not know what was intention of this functions author, there is no one comment about how to use options in this function and what thay exactly do so I understend them as top|center according to measured string boundary. Assuming that Top mean top of the bitmap make no sense for me because it is way easier to do manualy than align string boundary

@mmikeww
Copy link
Owner Author

mmikeww commented May 23, 2018

Ah yes this is a good point. So for the horizontal alignment, it DOES use the string boundary, instead of the full bitmap. Look at this for Example 8:

Options := "w100 Center cbbffffff"
msgbox Gdip_TextToGraphics(G, "Tutorial 8`n`nThank you for trying this example", Options, Font, Width, Height)

Here, it centers horiztonally within the w100 boundary

So perhaps vertical alignment should also be within the boundary. I just think this is a significant change from what the author tic originally intended

@smarq8
Copy link

smarq8 commented May 23, 2018

So instead of 'overwrite' oryginal intention then best way will be probably 'create' new intention ;). I already lost many hours many times for some of my scripts because of this function.

@mmikeww mmikeww changed the title Gdip_TextToGraphics Gdip_TextToGraphics vertical alignment May 23, 2018
@mmikeww
Copy link
Owner Author

mmikeww commented May 23, 2018

So instead of 'overwrite' oryginal intention then best way will be probably 'create' new intention ;). I already lost many hours many times for some of my scripts because of this function.

Yeah I agree its a good idea for you to create your new function Gdip_TextToGraphics2

I don't know yet what choice I should make for this library here, since we are trying to be backwards compatible..

@mmikeww
Copy link
Owner Author

mmikeww commented May 23, 2018

Here is the full description of what we're talking about.

Should the vertical alignment parameter be relative to the entire bitmap? Or relative to the bounding area of the text?

First the code for the examples, and then the screenshots below

#SingleInstance Force
;#NoEnv
;SetBatchLines -1
#Include ../Gdip_All.ahk
If !pToken := Gdip_Startup()
{
	MsgBox "Gdiplus failed to start. Please ensure you have gdiplus on your system"
	ExitApp
}
OnExit("ExitFunc")
Width := 600, Height := 400

;AHK v1
;Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
;Gui, 1: Add, Edit, w%Width% h20 y300 vMeEdit
;Gui, 1: Show, NA
Gui1 := GuiCreate("-Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs")
Gui1.Add("Edit", "w" Width " h20 y300 vMeEdit", "")
Gui1.Show("NA")
hwnd1 := WinExist()
hbm := CreateDIBSection(Width, Height)
hdc := CreateCompatibleDC()
obm := SelectObject(hdc, hbm)
G := Gdip_GraphicsFromHDC(hdc)
Gdip_SetSmoothingMode(G, 4)
pBrush := Gdip_BrushCreateSolid(0xaa000000)
Gdip_FillRoundedRectangle(G, pBrush, 0, 0, Width, Height, 20)
Gdip_DeleteBrush(pBrush)
Font := "Arial"
If !Gdip_FontFamilyCreate(Font)
{
	MsgBox "The font you have specified does not exist on the system"
	ExitApp
}
pPen := Gdip_CreatePen(0xffff0000, 2)
Gdip_DrawRectangle(G, pPen, 300, 50, 200, 200)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Options := "x300 y50 h200 w200 s20 Top cbbffffff"     ; <------------ change Top|Bottom|vCenter
;;;;;;;;;;;;;;;;;;;;;;;;;;;;
Gdip_TextToGraphics(G, "Tutorial 8`nThank you for trying this example", Options, Font, Width, Height)
UpdateLayeredWindow(hwnd1, hdc, (A_ScreenWidth-Width)//2, (A_ScreenHeight-Height)//2, Width, Height)
OnMessage(0x201, "WM_LBUTTONDOWN")
SelectObject(hdc, obm)
DeleteObject(hbm)
DeleteDC(hdc)
Gdip_DeleteGraphics(G)
Return

WM_LBUTTONDOWN()
{
   PostMessage 0xA1, 2
}

ExitFunc()
{
   global
   ; gdi+ may now be shutdown on exiting the program
   Gdip_Shutdown(pToken)
}

Esc::ExitApp

When you run this code, you will see the dark gray GUI which represents the full bitmap, and you will see a red rectangle which represents the boundary of the text which we specify in the Options parameter:
Options := "x300 y50 h200 w200

Top

Here is the default result when you use Top. It aligns with the top of the full bitmap, not with the text boundary:

top default

Compared to potentially using the text boundary:

top potential

So for "Top", it appears tic originally planned on this being the absolute vertical position for the whole bitmap.

vCenter

Here is the default result when you use vCenter. It aligns relative to the text boundary, not to the full surrounding bitmap. This is OPPOSITE to what the Top option does:

vcenter default

If vCenter were to align relative to the full bitmap, then it would look like this:

vcenter potential

Bottom

Finally, the Bottom option is quirky, when used by default. It just uses the h option as the y-coordinate, which is clearly not the "bottom" of anything:

bottom default

If we omit the h option and use this: Options := "x300 y50 w200 s20 Bottom cbbffffff"
Then we would get this following result. At least this is the bottom of the full bitmap:

bottom potential 2

Alternatively if we wanted to be at the bottom of the text boundary, we'd want this:

bottom potential 1

Conclusion

My guess is that tic ( @tariqporter ) originally intended this vertical alignment to be to the surrounding bitmap, and not relative to the text boundary. I think this is confirmed by how he coded the Top, and also the Bottom when no h is specified. But its just a guess, because as noted above, the vCenter contradicts this, and instead uses the text boundary. So there is a valid dispute as to the original intent. Should the Top|Bottom|vCenter options ignore and override any y-coordinates, and use the absolute position on the whole bitmap? Or should they respect the y-coordiante and align relative to it? What is clear, is that there is no consistency.

However, @smarq8 is suggesting that all of these alignments be relative to the text boundary (which is the red rectangle in the screenshots). This is a very valid request as well.

Since a change like this would break existing scripts, I don't think the Gdip_TextToGraphics() function should be changed right now in this library. This v2-GDIP library intends to be backwards compatible with the old Gdip library, so I don't think its our place to take this liberty. But this is certainly open for discussion.

For now I think I will only add the error checking. I will keep this issue open since it is unresolved and also as a reference point for other people. If you wanted to use the text boundary, then you would want the changes in the forum post originally linked at the top of this issue where the problem was first reported

@smarq8
Copy link

smarq8 commented May 23, 2018

just to be clear, here is what I always expected form this function. Crossing red lines are coordinates for function:


Gdip_TextToGraphics2(G, "Bottom Right",   "x100 y100 cbbffffff Bottom Right")
Gdip_TextToGraphics2(G, "Bottom Left",    "x100 y100 cbbffffff Bottom Left")
Gdip_TextToGraphics2(G, "Top LEft",       "x100 y100 cbbffffff Top Left")
Gdip_TextToGraphics2(G, "Top Right",      "x100 y100 cbbffffff Top Right")
Gdip_TextToGraphics2(G, "Bottom Center",  "x100 y300 cbbffffff Bottom Center")
Gdip_TextToGraphics2(G, "Top Center",     "x100 y300 cbbffffff Top Center")
Gdip_TextToGraphics2(G, "vCenter Center", "x400 y300 cbbffffff vCenter Center")
Gdip_TextToGraphics2(G, "vCenter Right",  "x400 y100 cbbffffff vCenter Right")
Gdip_TextToGraphics2(G, "vCenter Left",   "x400 y100 cbbffffff vCenter Left")

screenshot 1527104799

and here are resoult from oryginal function:
screenshot 1527104793

PS
by wathing mmikeww samples i catch using that w/h option align is 'almost' (because some samples are missing or in wrong place) reffer to rect instead of align string boundary to coords


Gdip_TextToGraphics2(G, "Bottom Right",    "w300 h200 x100 y100 cbbffffff Bottom Right")
Gdip_TextToGraphics2(G, "Bottom Left",     "w300 h200 x100 y100 cbbffffff Bottom Left")
Gdip_TextToGraphics2(G, "Top LEft",        "w300 h200 x100 y100 cbbffffff Top Left")
Gdip_TextToGraphics2(G, "Top Right",       "w300 h200 x100 y100 cbbffffff Top Right")
Gdip_TextToGraphics2(G, "Bottom Center",   "w300 h200 x100 y300 cbbffffff Bottom Center")
Gdip_TextToGraphics2(G, "Top Center",      "w300 h200 x100 y300 cbbffffff Top Center")
Gdip_TextToGraphics2(G, "vCenter Center",  "w300 h200 x400 y300 cbbffffff vCenter Center")
Gdip_TextToGraphics2(G, "vCenter Right",   "w300 h200 x400 y100 cbbffffff vCenter Right")
Gdip_TextToGraphics2(G, "vCenter Left",    "w300 h200 x400 y100 cbbffffff vCenter Left")

screenshot 1527105065
and same thing with oryginal function again unexpected behavior for me:
screenshot 1527105113

@AHK-just-me
Copy link
Contributor

AHK-just-me commented May 27, 2018

This is my try on Gdip_TextToGraphics2(). I added Gdip_SetStringFormatLineAlign() to let GDI+ perform the vertical alignment within the layout rectangle.

You need to pass the width either as wnnn in Options or in the Width parameter for horizontal and the height either as hnnn in Options or in the Height parameter for vertical alignment. Otherwise the function will return -1.

What do you think about it?

BTW: There is no need to call MultiByteToWideChar() if the script isn't designed to work on AHK Basic unless the passed string will be changed. It can be passed as "WStr".

; gdi+ ahk tutorial 8 written by tic (Tariq Porter)
; Requires Gdip.ahk either in your Lib folder as standard library or using #Include
;
; Tutorial to write text onto a gui

#SingleInstance, Force
#NoEnv
SetBatchLines, -1

; Uncomment if Gdip.ahk is not in your standard library
#Include, Gdip_All.ahk

; Start gdi+
If !(pToken := Gdip_Startup())
{
   MsgBox, 48, gdiplus error!, Gdiplus failed to start. Please ensure you have gdiplus on your system
   ExitApp
}
OnExit, Exit

; Set the width and height we want as our drawing area, to draw everything in. This will be the dimensions of our bitmap
Width := 300
Height := 200

; Create a layered window (+E0x80000 : must be used for UpdateLayeredWindow to work!) that is always on top (+AlwaysOnTop), has no taskbar entry or caption
Gui, 1: -Caption +E0x80000 +LastFound +AlwaysOnTop +ToolWindow +OwnDialogs
Gui, 1: Add, Edit, w%Width% h20 y300, vMeEdit
; Show the window
Gui, 1: Show, NA

; Get a handle to this window we have created in order to update it later
hwnd1 := WinExist()

; Create a gdi bitmap with width and height of what we are going to draw into it. This is the entire drawing area for everything
hbm := CreateDIBSection(Width, Height)

; Get a device context compatible with the screen
hdc := CreateCompatibleDC()

; Select the bitmap into the device context
obm := SelectObject(hdc, hbm)

; Get a pointer to the graphics of the bitmap, for use with drawing functions
G := Gdip_GraphicsFromHDC(hdc)

; Set the smoothing mode to antialias = 4 to make shapes appear smother (only used for vector drawing and filling)
Gdip_SetSmoothingMode(G, 4)

; Create a partially transparent, black brush (ARGB = Transparency, red, green, blue) to draw a rounded rectangle with
pBrush := Gdip_BrushCreateSolid(0xaa000000)

; Fill the graphics of the bitmap with a rounded rectangle using the brush created
; Filling the entire graphics - from coordinates (0, 0) the entire width and height
; The last parameter (20) is the radius of the circles used for the rounded corners
Gdip_FillRoundedRectangle(G, pBrush, 0, 0, Width, Height, 20)

; Delete the brush as it is no longer needed and wastes memory
Gdip_DeleteBrush(pBrush)

; We can specify the font to use. Here we use Arial as most systems should have this installed
Font := "Arial"
; Next we can check that the user actually has the font that we wish them to use
; If they do not then we can do something about it. I choose to give a wraning and exit!
If !Gdip_FontFamilyCreate(Font)
{
   MsgBox, 48, Font error!, The font you have specified does not exist on the system
   ExitApp
}

; There are a lot of things to cover with the function Gdip_TextToGraphics

; The 1st parameter is the graphics we wish to use (our canvas)

; The 2nd parameter is the text we wish to write. It can include new lines `n

; The 3rd parameter, the options are where all the action takes place...
; You can write literal x and y coordinates such as x20 y50 which would place the text at that position in pixels
; or you can include the last 2 parameters (Width and Height of the Graphics we will use) and then you can use x10p
; which will place the text at 10% of the width and y30p which is 30% of the height
; The same percentage marker may be used for width and height also, so w80p makes the bounding box of the rectangle the text
; will be written to 80% of the width of the graphics. If either is missed (as I have missed height) then the height of the bounding
; box will be made to be the height of the graphics, so 100%

; Any of the following words may be used also: Regular,Bold,Italic,BoldItalic,Underline,Strikeout to perform their associated action

; To justify the text any of the following may be used: Near,Left,Centre,Center,Far,Right with different spelling of words for convenience

; The rendering hint (the quality of the antialiasing of the text) can be specified with r, whose values may be:
; SystemDefault = 0
; SingleBitPerPixelGridFit = 1
; SingleBitPerPixel = 2
; AntiAliasGridFit = 3
; AntiAlias = 4

; The size can simply be specified with s

; The colour and opacity can be specified for the text also by specifying the ARGB as demonstrated with other functions such as the brush
; So cffff0000 would make a fully opaque red brush, so it is: cARGB (the literal letter c, follwed by the ARGB)

; The 4th parameter is the name of the font you wish to use

; As mentioned previously, you don not need to specify the last 2 parameters, the width and height, unless
; you are planning on using the p option with the x,y,w,h to use the percentage
Options := "x10p y30p w80p Center cbbffffff r4 s20 Underline Italic"
; Gdip_TextToGraphics(G, "Tutorial 8`n`nThank you for trying this example", Options, Font, Width, Height)
Gdip_TextToGraphics2(G, "Tutorial 8`n`nThank you for trying this example", Options, Font, Width, Height)

; Update the specified window we have created (hwnd1) with a handle to our bitmap (hdc), specifying the x,y,w,h we want it positioned on our screen
; With some simple maths we can place the gui in the centre of our primary monitor horizontally and vertically at the specified heigth and width
UpdateLayeredWindow(hwnd1, hdc, (A_ScreenWidth-Width)//2, (A_ScreenHeight-Height)//2, Width, Height)

; By placing this OnMessage here. The function WM_LBUTTONDOWN will be called every time the user left clicks on the gui
OnMessage(0x201, "WM_LBUTTONDOWN")

; Select the object back into the hdc
SelectObject(hdc, obm)

; Now the bitmap may be deleted
DeleteObject(hbm)

; Also the device context related to the bitmap may be deleted
DeleteDC(hdc)

; The graphics may now be deleted
Gdip_DeleteGraphics(G)
Return

;#######################################################################
; This function is called every time the user clicks on the gui
; The PostMessage will act on the last found window (this being the gui that launched the subroutine, hence the last parameter not being needed)
WM_LBUTTONDOWN()
{
   PostMessage, 0xA1, 2
}
;#######################################################################

Esc::
Exit:
; gdi+ may now be shutdown on exiting the program
Gdip_Shutdown(pToken)
ExitApp
Return

; ================================================================================================================================
; Additional GDIP functions
; ================================================================================================================================
; ================================================================================================================================
Gdip_TextToGraphics2(pGraphics, Text, Options, FontName := "Arial", Width := "", Height := "", Measure := 0) {
   GW := Width, GH:= Height
   ; Get the specified options - 1st part
   RegExMatch(Options, "i)\bX([\-\d\.]+)(p*)\b", RX) ; x
   RegExMatch(Options, "i)\bY([\-\d\.]+)(p*)\b", RY) ; y
   RegExMatch(Options, "i)\bW([\-\d\.]+)(p*)\b", RW) ; w
   RegExMatch(Options, "i)\bH([\-\d\.]+)(p*)\b", RH) ; h
   RegExMatch(Options, "i)\bC(?!(enter))([a-f\d]{8})\b", Colour) ; c
   RegExMatch(Options, "i)\bR(\d)\b", Rendering) ; r
   RegExMatch(Options, "i)\bS(\d+)(p*)\b", FontSize) ; s
   RegExMatch(Options, "i)\bNoWrap\b", NoWrap) ; NoWrap
   ; If X, Y, W, H, or S has been specified as percentage (p), the related Width or Height parameter must be passed also.
   If (!GW && (RX2 || RW2)) || (!GH && (RY2 || RH2 || FontSize2))
      Return -1
   ; Get the specified options - 2nd part
   FontStyle := 0
   For K, V In {Regular: 0, Bold: 1, Italic: 2, BoldItalic: 3, Underline: 4, Strikeout: 8}
      If RegExMatch(Options, "i)\b" . K . "\b")
         FontStyle |= V
   Align := 0
   For K, V In {Left: 0, Center: 1, Centre: 1, Right: 2}
      If RegExMatch(Options, "i)\b" . K . "\b")
         Align := V
   LineAlign := 0
   For K, V In {Top: 0, vCenter: 1, vCentre: 1, Bottom: 2}
      If RegExMatch(Options, "i)\b" . K . "\b")
         LineAlign := V
   ; Create the values for the drawing rectangle
   RX := (RX1 != "") ? RX2 ? (GW * RX1) / 100 : RX1 : 0
   RY := (RY1 != "") ? RY2 ? (GH * RY1) / 100 : RY1 : 0
   RW := (RW1 != "") ? RW2 ? (GW * RW1) / 100 : RW1 : (GW ? GW - RX : 0)
   RH := (RH1 != "") ? RH2 ? (GH * RH1) / 100 : RH1 : (GH ? GH - RY : 0)
   ; If non-default alignment has been specified, the related Width or Height parameter must be passed also.
   If (Align && !RW) || (LineAlign && !RH)
      Return -1
   ; Rendering
   Rendering := ((Rendering1 >= 0) && (Rendering1 <= 5)) ? Rendering1 : 4
   If Gdip_SetTextRenderingHint(pGraphics, Rendering)
      Return -2
   ; Font
   FontSize := (FontSize1 > 0) ? FontSize2 ? (GH * FontSize1) / 100 : FontSize1 : 12
   If !(hFamily := Gdip_FontFamilyCreate(FontName))
      Return -3
   If !(hFont := Gdip_FontCreate(hFamily, FontSize, FontStyle)) {
      Gdip_DeleteFontFamily(hFamily)
      Return -4
   }
   ; StringFormat
   FormatStyle := 0x4000 | (NoWrap ? 0x1000 : 0) ; 0x4000 = StringFormatFlagsNoClip, 0x1000 = StringFormatFlagsNoWrap
   If !(hFormat := Gdip_StringFormatCreate(FormatStyle)) {
      Gdip_DeleteFont(hFont)
      Gdip_DeleteFontFamily(hFamily)
      Return -5
   }
   Gdip_SetStringFormatAlign(hFormat, Align)
   Gdip_SetStringFormatLineAlign(hFormat, LineAlign)
   ; Brush: If a brush was passed in the c option, use it; otherwise create a brush
   Colour := "0x" . (Colour2 ? Colour2 : "FF000000")
   If !(pBrush := Gdip_CloneBrush(Colour2)) && !(pBrush := Gdip_BrushCreateSolid(Colour)) {
      Gdip_DeleteStringFormat(hFormat)
      Gdip_DeleteFont(hFont)
      Gdip_DeleteFontFamily(hFamily)
      Return -6
   }
   ; Draw or measure the text
   CreateRectF(RC, RX, RY, RW, RH)
   If (Measure)
      ReturnRC := Gdip_MeasureString(pGraphics, Text, hFont, hFormat, RC)
   Else
      Result := Gdip_DrawString(pGraphics, Text, hFont, hFormat, pBrush, RC)
   ; Free resources
   Gdip_DeleteBrush(pBrush)
   Gdip_DeleteStringFormat(hFormat)
   Gdip_DeleteFont(hFont)
   Gdip_DeleteFontFamily(hFamily)
   ; Return
   Return (Measure ? ReturnRC : Result)
}
; ================================================================================================================================
; hFormat:     Pointer to a StringFormat object returned by Gdip_StringFormatCreate()
; LineAlign:   Vertical alignment: 0 = top, 1 = center, 2 = bottom
; ================================================================================================================================
Gdip_SetStringFormatLineAlign(hFormat, LineAlign) {
   Return DllCall("Gdiplus.dll\GdipSetStringFormatLineAlign", "Ptr", hFormat, "Int", LineAlign)
}

@mmikeww
Copy link
Owner Author

mmikeww commented May 27, 2018

@smarq8

just to be clear, here is what I always expected form this function. Crossing red lines are coordinates for function:

Gdip_TextToGraphics2(G, "Bottom Right",   "x100 y100 cbbffffff Bottom Right")

This is yet a 3rd option. This doesn't align with either the full graphics dimensions, nor does it align with the text boundary rect. Instead, you just want it to align with the coordinate directly. I don't agree that this 3rd option is how the func should behave. But it works for your specific use-case. Regardless, none of these options are wrong or right, we'd just need to decide on what our intent is and what we want the function to do.

PS
by wathing mmikeww samples i catch using that w/h option align is 'almost' (because some samples are missing or in wrong place) reffer to rect instead of align string boundary to coords

I don't think anything is 'missing' or 'in wrong place'. In these examples, I think they are off-screen because that's where the boundary of the rect is.

--

@AHK-just-me

What do you think about it?

Most of my quick tests looked good. Everything is aligning to the boundary of the text rect. Would be nice to have a suite of test cases. That's one of the benefits of TDD.

Tic originally also allowed Near/Far and Up/Down as alternative words for the alignment options that you had left out (maybe you left them out intentionally because hardly anyone uses those).

Also, your func only works on AHK v1, but this repository is specifically for the AHK v1/v2 backward compatible version of the library

BTW: There is no need to call MultiByteToWideChar() if the script isn't designed to work on AHK Basic unless the passed string will be changed. It can be passed as "WStr".

AHK_L v1.1 still has ANSI versions. Does that mattter? But yes you mentioned something similar in the past, and I created Issue #2

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

No branches or pull requests

3 participants