How does one reproduce the inset text style when drawing text with Mac OS X Cocoa? - cocoa

I'm talking about the groove style of the text on focussed title bars, or safari's bookmarks bar for example. Is there an easy way to reproduce this style when using:
[string drawAtPoint:... withAttributes:...];

If you want it to look perfect, you'll need to draw the text twice.
As you can see when zooming in on labels below toolbar items in any app, or for instance the bookmarks bar in Safari (Control+scroll up, control+option+\ to toggle smoothing of the zoomed in image), the text is rendered with sub-pixel anti-aliasing, at least when "Font smoothing style:" in the "Appearance" system preferences is set to medium, which it will be by default on Macs with a built-in or external Apple flat-panel display.
NSShadow can not be used with sub-pixel anti-aliasing, so if you simply set an NSShadowAttributeName in the attributes dictionary you're drawing your string with, you will notice sub-pixel anti-aliasing is MIA when you zoom in on your rendered text.  Due to the way NSShadow is designed, no matter what color you set your NSShadow instance to —even if it is opaque— it will always be drawn with an alpha channel, making sub-pixel antialiasing impossible.
The solution is really very simple:
Draw your text once with a white color with some transparancy,
Then draw it once more on top of that, a pixel higher in a shade of grey of your liking with no transparancy.
Your 'shadow' will draw without sub-pixel antialiasing, but the actual text on top op of it will draw with it, giving you the exact same effect as standard Cocoa toolbar button item labels, or items in the Safari bookmarks bar.
EDIT: It seems that Safari's bookmarks bar items draw their 'shadows' with sub-pixel accuracy as well, so the way they did it is probably by choosing an opaque shade of gray for the white 'shadow' text as well; drawback of that approach: you are tying your drawing code to only work well on a particular background color, e.g. if your elements will be used on a blue background, you'll want to set that color to a light shade of blue, to appear like it's semi-transparent white.

Draw it with an un-shadow below it. Use a shadow with color white, opacity 50% or so, blur 0, offset 1 pt down.
A simple way to do this is to simply draw the text twice. The first time, you draw it 1 pt lower, in white, at 50% opacity. The second time, you draw it in the desired position, in the desired color, at the desired (probably 100%) opacity.

Related

DirectX Resize shows win32 background at Edges

When resizing down in DirectX I noticed a flicker along the bottom/right edges.
If you fix the size of the swapchain (in red), and set the win32 background to green you will get the following on a resize down:
It appears that the window size lags behind the mouse position ("Drag Rectangle") but the area DirectX fills (in red and black) matches the Drag Rectangle, with the remainder to be painted with the window background color (green).
The DirectX Utility Toolkit (DXUT) didn't have this problem. Experimenting with their settings I found that setting DXGI_SWAP_CHAIN_DESC::SwapEffect = DXGI_SWAP_EFFECT_DISCARD would just paint the screen green (the window background color) during a sizemove. I assume that DXUT has their own special handling for when win32 enters a modal sizemove loop in order to display DirectX content during a sizemove.
DXGI_SWAP_EFFECT_DISCARD is part of the old blit mode presentation model. Notably it cant have DXGI_SWAP_CHAIN_DESC1::Scaling = DXGI_SCALING_NONE the scaling must be stretched to the window size. So my best guess is this behavior is due to the implementation of the flip presentation model (it flips a rectangle too small (black) and then covers by painting the rest green).
Does anyone know how to stop the win32 background from showing?
Edit:
Thanks to IInspectable! I can confirm the WS_EX_NOREDIRECTIONBITMAP extended style works: it stops the artifact from the win32 background showing
I reproduced the exact same behavior when using CreateSwapChainForComposition() with DirectComposition as I got using CreateSwapChainForHwnd().
This means that there are two path for pixels to get to the screen. The green pixels are going through the Redirection Surface. Hence, explicitly requesting WS_EX_NOREDIRECTIONBITMAP prevents any drawing through a Redirection Surface stopping the win32 background from showing.
The other path is the flip presentation behavior which is how the red and black pixels are get displayed. Hence, not using flip presentation when resizing also stops the win32 background from being shown.
There must be a bug with DWM: when there is a Redirection Surface, the clipping to prevent the swapchain's contents extending past the window is smaller than the redirection surface allowing it to be seen along the bottom/right edges.
There are two observations of interest:
when using WS_EX_LAYOUTRTL or manually positioning a IDCompositionVisual to the right edge of the screen with GetClientRect(), the swapchains contents are correctly position, but still clipped.
when using WS_EX_NOREDIRECTIONBITMAP the window`s nonclient area lines up with the contents of the swapchain rather than the swapchains contents being clipped
These observations would seam to imply that the cause of the issue is that DWM is using it's prefered size for the window size sometimes and the size of the redirection surface othertimes.

Core Text on Retina Macs

I use Core Text to draw text to an offscreen bitmap context using CTLineDraw(). The bitmap is then processed internally before it is drawn to my window.
The problem here is that bitmap contexts aren't scaled on Retina Macs. Thus, on a Retina Mac, the text is still drawn at 72dpi to the bitmap but it should be drawn in 144dpi of course, because the pixel density is twice as high. Thus, the text currently looks blurry because it is drawn at 72dpi to the offscreen bitmap and this bitmap is then scaled when it is drawn to the window.
What is the best way to make Core Text Retina-aware in this context? Should I simply pass a transformation matrix to CTFontCreateWithName() that contains the screen's backingScaleFactor in its scale coefficients? That does look a little hackish, though. That's why I'm asking for some feedback or a better idea...

Setting the background to transparent using GIMP

Using GIMP 2, I have an image of a grey chair on a white background, as below:
I now want to set the background to transparent. Therefore, I decided to use GIMP's "Color To Alpha" tool. So, I told it to set all pixels which are white (255, 255, 255) to transparent, as below:
This did set all white pixels to transparent. However, it also set the grey pixels on the chair to be partially transparent, as below:
So when I export this image and place it in front of a background, there is no white box around the chair -- but the background partially shows through the chair.
What am I doing wrong?
First, this question is offtopic here, and should be on https://graphicdesign.stackexchange.com .
Second, it is trivial enough just to answer: the color to alpha plug-in is not there to turn a single color, as seem on the image, to transparency: it is a sophisticated plug-in that will remove one color of your image in a way that, if you lace the new image over a background of the same color the color you removed, you get the original image back.
Thus, in your case, it removed the "whiteness" of your chair, transforming all pixels to different opaque shades of black - so that when placed over white, you get the original image.
To simply remove the white, you have to cick on the Select By Color tool (by default th 5th icon on the toolbox), click on the white background to have it selected, and then just edit->cut. (It won't work if your image layer does not have transparency to start with - if that is the case, prior to edit->cut do Layer->Transparency->Add Alpha Channel).
If you get aliased borders, then, after edit>cut, but prior to dismissing your selection, you can do Select->Border... by 1 or 2px, and then use the color to alpha filter with White on this selection.
For more information on Color to Alpha, I have this other answer its use and comparison with edit-cut here: https://graphicdesign.stackexchange.com/questions/28058/gimp-color-to-alpha-is-not-selectable/28097#28097
Just use a selection to restrict the action of Color to alpha where it matters: backgroundand edge pixels:
Select background with fuzzy select
Select>Grow by one pixel so that the selection ofverlaps the edge pixels
Color>Color to alpha

NSColor transparency on black background?

In the background of my view, I draw a light blue color. And in the middle, i have a square box that is supposed to have an even lighter gray in it that has a 20% transparency. But for some reason the transparency is on top of a black background instead of a blue. I'm sorry If i'm not being clear.
You're probably using the wrong compositing mode to draw the smaller box. Show us your code.

Window border width and height

I'm writing a direct3d application and after noticing strange bugs such as anti-aliasing occurring even when it was turned off and the mouse pointer not lining up to things with the same coordinates as itself I discovered that when creating a window the width and height parameters include the border. The program was rendering a 800x600 graphics output to a window of the same size, but because of the borders it was squished into 792x566 rectangle. I've increased the size of the window to compensate, but this does not work if the system uses a border style other the standard XP style. (Classic style, for example)
Is there a way to tell what the border width and heights will be before I create the window?
Another option would be to make sure the D3D surface is the same size as the client rectangle size (GetClientRect()). Then you know you'll render to the appropriate size and not have to worry at all about the width of menus, borders, etc.
It sounds like you are looking for the GetSystemMetrics function. For example, the border width in pixels is returned by
GetSystemMetrics(SM_CXBORDER)
ADDED: For the total size you will need to add together the various "pieces" of the non-client area: border, frame sizes, title bars, etc.

Resources