No color in FMX TFont, why? - firemonkey

In XE6 I noticed that the Firemonkey TFont class has no way to specify the font's color whereas the Vcl.TFont does. Does anyone know the reason for this?
FMX.TFont only has properties for Family, Size and Style

We can only speculate on the reason. The GDI+ DrawString function uses a Brush (=Fill in FireMonkey) for filling the string. It looks like they just decided to do it in a similar way. The name FillText also suggests some association with the Fill.
Canvas.Fill.Color := TAlphaColorRec.Aqua;
Canvas.FillText(RectF(0, 0, 100, 100), 'test', False, 1.0, [], TTextAlign.Center);

Related

Phaser 3: Text displayed using TrueType (.ttf) font renders distorted/blurred

I'm loading a .ttf file via CSS and definition of font-face.
However, in the game the text renders blurry.
This is what I tried first (the font name is truetypetest):
this.sampleText = this.scene.add.text(0, 0, 'Almost clear text', { fontFamily: 'truetypetest' });
This actually renders almost clearly:
Almost clear text
There is still some sort of lighter 'shadow' if you look carefully. Setting the resolution arbitrarily high via the below gives what I want:
this.sampleText = this.scene.add.text(0, 0, 'Clear text', { fontFamily: 'truetypetest' }).setResolution(10);
This renders clearly:
Clear text
However, I don't want to be setting resolution this way as it's expensive memory-wise.
Furthermore, if I avoid setting the resolution AND specify a specific fontSize, via:
this.sampleText = this.scene.add.text(0, 0, 'Blurry text', { fontFamily: 'truetypetest', fontSize: '20px' });
This renders as blurry text:
Blurry text
I should mention that I'm rendering the text inside a container (GameObjects.Container). Also, and I suspect this is the key problem - I'm zooming the canvas using:
scale: {
parent: 'game-canvas',
zoom: 2,
autoCenter: Phaser.Scale.CENTER_BOTH,
}
I can't avoid using the zoom at this stage as the art is based off of this requirement. I've also tried using Bitmap font with no luck.
So my question is how do I use my custom font in my game that can render clear text for a wide range of different fontSize?
Thanks!
UPDATE
I've tried all of the following but with no luck:
Used Bitmap Fonts (including adding png font-sheets for different sizes
Tried rex WebFont Loader plugin: https://rexrainbow.github.io/phaser3-rex-notes/docs/site/webfontloader/#test-string (loads font but still blurry)
Used a normal font like Roboto from the Google Font API. So the problem is not isolated to my particular font style (pixel-style font)
Tried following the method described here: https://phaser.io/examples/v3/view/game-objects/text/custom-webfont (CSS injection and custom webfont loading)
Tried multiples of font sizes
Tried autoRound=true
I find it difficult to believe what I'm trying to do is not possible. Its only text being rendered within a container. I would have thought there's a way of ensuring a single font can be used across a general range of sizes within the game? Failing that, I wouldn't mind using a more exhaustive strategy (multiple different font files at different sizes) if that is needed. There MUST be a way of rendering crisp text within a game? :(

Stroke width, or line material in three-globe

Just trying to up the stroke width a little on the country polygons for three-globe.
There doesn't appear to be a helper function for this material or any settings beyond color.
I had the bright idea of looping through all the children of the globe object, very crude but:
for (let i in Globe.children[0].children[4].children){
const child = Globe.children[0].children[4].children[i];
child.children[1].material.linewidth = 3;
child.children[1].material.color = new THREE.Color('rgba(255,255,255,1)');
}
This appears to have no effect on the line width. It does, however, successfully change the color, so I think I'm close, though I really hope there's a better way than this.
I'm sorry to inform you that the .linewidth property is very poorly supported due to OpenGL limitations. You can see an explanation in the LineBasicMaterial.linewidth documentation
Due to limitations of the OpenGL Core Profile with the WebGL renderer on most platforms linewidth will always be 1 regardless of the set value.
You'll run into this issue if you're using THREE.Line or THREE.LineSegments. However, there is an alternative you could use with THREE.Line2, which circumvents the limitation by drawing lots of instanced gl.TRIANGLES instead of gl.LINE. You can see it in action in this example. In fact, there are 3 demos of fat lines, each one with a slightly different implementation. You would then have to substitute the outlines of the country with your own fat lines.

Borderless window. How to add a shadow and remove 1px border?

I need to create a borderless window with specified background color. I know how to remove a non client area and get something like this:
It's cool but not truly what I want. If you take a closer look at any aero window - there's a shadow around it (actually this is not a shadow but some glow). I found somewhere that I can use this code to add a shadow:
const MARGINS shadow_on = { 1, 1, 1, 1 };
DwmExtendFrameIntoClientArea(hwnd, &shadow_on);
It's almost do it's job (thought this is absolutely not clear to me -
documentation says nothing about relationship of shadow and this function). Almost. There's a thin border appeared around the window. It looks like it's semitransparent and it breaks the look and feel of the window:
I know that it's possible - the visual studio even change the color of this border somehow!
Update: as IInspectable noticed in comments I can use negative margins in DwmExtendFrameIntoClientArea(). I set -1 value and got this result:
As you can see - it's even weirder. I tried to fill a background with color, but without luck.
To remove one pixel border after calling this function:
const MARGINS shadow_on = { 1, 1, 1, 1 };
DwmExtendFrameIntoClientArea(hwnd, &shadow_on);
You need to override WndProc WM_NCCALCSIZE message, and return 0 as the result.
Also you need to create window using WS_CAPTION style. (On Windows XP this code won't produce rectangular window, but there is no shadow on WinXP, so on Windows XP you should fallback to WS_POPUP window style)
By the way, to add shadow it is enough to use this margins:
const MARGINS shadow_on = { 1, 0, 0, 0 };
Here is clean windows API code example how to create such window, it is written on Delphi: https://stackoverflow.com/a/44489430/877099

Win32: How to make drop shadow honor non-rectangular Layered window?

i've created a layered window by adding the the WS_EX_LAYERED extended style:
wndClass.ExStyle = wndClass.ExStyle | WS_EX_LAYERED;
Windows will use black as the chroma key color value. i'm going to leave a large border of black to make the problem obvious:
After the window is constructed, i tell it to use black as a chroma-key color:
SetLayeredWindowAttributes(hwnd, 0x00000000, 255, LWA_COLORKEY);
Now the popup layered window appears partially transparent:
The problem is the final step. i want to use CS_DROPSHADOW class style, available since Windows XP, to create a drop-shadow:
wndClass.Style = wndClass.Style | CS_DROPSHADOW;
The drop shadow appears, but the shadow surrounds the original rectangular window, and doesn't take into account the window's transparency provided by the layered window:
Does anyone know what magical option i've missed somewhere that will make the drop shadow honor the non-rectangular layered window?
Another example of where this issue appears is when you don't include the 6px padding/margin. The hint window as drawn by Windows® themes is non-rectangular. This leaves a small visible gap where the window is transparent, but the drop shadow does not appear:
Microsoft has managed to make it work, as you can see from this hint from Internet Explorer:
Looking closer at a Windows tooltips class hint window. Using SpyXX - i can get its window rect, and class styles:
SpyXX says:
Rectangle: (440, 229)-(544, 249), 104x20
Restored Rect: (440, 229)-(544, 249), 104x20
Client Rect: (0, 0)-(104, 20), 104x20
So everything points to the window itself being 104x20 pixels, with the drop shadow outside the window itself. (Which is consistent with CS_DROPSHADOW.)
Next i can look at the styles of the tooltips window class:
Windows Styles: 94000001
WS_POPUP 80000000
WS_VISIBLE 10000000
WS_CLIPSIBLINGS 4000000
TTS_ALWAYSTIP 1
Extended Styles: 00080088
WS_EX_LAYERED 80000
WS_EX_TOOLWIN 80
WS_EX_TOPMOST 8
Interestingly, it doesn't use CS_SAVEBITS (0x800); which is useful for small, short-lived, windows.
Nor does it use CS_DROPSHADOW (0x20000). So now i wonder how is it drawing outside its own window?
Note: Transparent layered windows is documented as the preferred technique over regions.
Edit: Layered Windows have been around with Windows 2000. CS_DropShadow was added with XP.
Transparent layered windows is documented as the preferred technique over regions.
However, CS_DROPSHADOW does pay attention to regions. If you crop or otherwise shape your window using a region, the drop-shadow will follow the new outline.
Fortunately, you can use regions with layered windows, and by combining the two get the effect you're looking for.
BTW: tooltips_class32 does use CS_DROPSHADOW - you won't see it in the window styles because it's a class style, not a window style.
Why don't you use LWA_ALPHA and build the shadow into the image?
Edit in reponse to your comment:
A) Doesn't stop you using an alpha channeled PNG for a shadow only. Blt the 2 images together and use as one single image.
B) Its not hard to generate a drop shadow. In the image you posted its black with 3 different alpha values.
C) But it doesn't work does it? ie Time to get creative.
D) Then don't try and get windows to do something it won't do for you.
E) Is entirely irrelevant. Layered windows handle that for you.
I strongly recommend you learn more about layered windows because they CAN help you to your goal.
Edit2: You have the bitmap. Its fairly easy to scan over the image and find which bits will be colour keyed (by identifying the black yourself) and hen modify that to have an alpha of 0 where everything else will have an alpha of 255 (Not: You may have to convert the image to a 32-bit image from a lower colour format, you can do this by creating a new DC and copying the image). This will give you the same effect with LWA_ALPHA as with LWA_COLORKEY. From there its fairly easy to identify the pixel at the edge, where the color changes to (R = 0, G = 0, B = 0, A = 0). You then change that first pixel to have a n alpha of 192, the one blow it to 128 and the one below to 64. You now have an alpha'd gradation below the image that will look like the shadow. You can adjust the alpha to get the effect you want.
CS_DROPSHADOW only works with standard rectangular windows. WS_EX_LAYERED windows don't support everything. They are more of a low-level, self-service method to draw exactly what you want.
To get a drop shadow, you'll have to generate the drop-shadow yourself from the alpha channel in the image.

Default button size?

How do I create a button control (with CreateWindow of a BUTTON window class) that has a standard system-wide size (especially height) that's consistent with the rest of Windows applications?
I should of course take DPI into account and probably other settings.
Remark: Using USE_CW_DEFAULT for width and height results in a 0, 0 size button, so that's not a solution.
In the perfect, hassle-free world...
To create a standard size button we would have to do this:
LONG units = GetDialogBaseUnits();
m_hButton = CreateWindow(TEXT("BUTTON"), TEXT("Close"),
WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON,
0, 0, MulDiv(LOWORD(units), 50, 4), MulDiv(HIWORD(units), 14, 8),
hwnd, NULL, hInst, NULL);
where 50 and 14 are respective DLU dimensions, 4 and 8 are horizontal and vertical dialog template units respectively, based on GetDialogBaseUnits() function documentation remarks.
Nothing's perfect
BUT as Anders pointed out, those metrics are based on the system font. If your window uses a shell dialog font or simply anything not making your eyes bleed, you're pretty much on your own.
To get your own "dialog" base units, you have to retrieve current text metrics with GetTextMetrics() and use character height and average width (tmHeight and tmAveCharWidth of the TEXTMETRIC struct respectively) and translate them with MulDiv by your own, unless you are in a dialog, then MapDialogRect() will do all the job for you.
Note that tmAveCharWidth only approximates the actual average character width so it's recommended to use a GetTextExtentPoint32() function on an alphabetic character set instead.
See:
How to calculate dialog box units based on the current font in Visual C++
How To Calculate Dialog Base Units with Non-System-Based Font
Simpler alternative
If buttons are the only control you want to resize automatically, you can also use BCM_GETIDEALSIZE message Button_GetIdealSize() macro (Windows XP and up only) to retrieve optimal width and height that fits anything the button contains, though it looks pretty ugly without any margins applied around the button's text.
This is what MSDN has to say: Design Specifications and Guidelines - Visual Design: Layout.
The default size of a button is 50x14 DLUs, which can be calculated to pixels using the examples shown for GetDialogBaseUnits.
The MapDialogRect function seems to do the calculation for you.
#macbirdie: you should NOT use GetDialogBaseUnits(), it is based on the default system font (Ugly bitmap font). You should use MapDialogRect()

Resources