Sign in Join
Wiki copytemporary

Cocoa Internals/Graphics: what changed

Revision 1 to 2. Removed lines have a minus sign; added lines have a plus sign.

OldNewLine
11## Colors
22
33Cocoa-WS should be using device-dependent colors to match colors across other widgetsets.
44
55That applies to color of Pen, Brush and Font.
66
77
88The “Device” color-space names represent color spaces in which component values are applied to devices as specified. There is no optimization or adjustment for differences between devices in how they render colors. If you know exactly which device is connected to a system and you want to print or display a certain color on that device, then it makes sense to use a appropriate device-dependent color space when creating NSColor objects. However, it is usually not the case that an application knows which devices are connected and their specific color spaces. If you specify components of a color in a device-dependent color space—let’s say NSDeviceRGBColorSpace—and then have several displays render this color, you will see several slightly different colors.
99
1010
1111To get around this problem you can use calibrated color spaces, which are designated by two of the color-space names in Table 1. A calibrated color space is a device-independent color space. The color spaces designated by NSCalibratedWhiteColorSpace and NSCalibratedRGBColorSpace color spaces are calibrated to a device that best represents devices in a particular class, such as color displays. It allows your application to present reasonably accurate colors when you are unsure about the color space of a device in a particular context.
1212
1313### System Colors
1414
1515NSColor class provides a large variety of system themed colors:
1616
17-<table>
18-<thead>
19-<tr>
20-<th><p>Constant</p></th>
21-<th><p>LCL definition</p></th>
22-<th><p>NSColor</p></th>
23-<th><p><a href="https://developer.apple.com/documentation/appkit/nscolor?language=objc">Cocoa definition</a></p></th>
24-</tr>
25-</thead>
26-<tbody>
27-<tr>
28-<td><p>clScrollBar</p></td>
29-<td><p>Scrollbar body</p></td>
30-<td><p>scrollBarColor</p></td>
31-<td><p>Returns the system color used for scroll “bars”—that is, for the groove in which a scroller’s knob moves</p></td>
32-</tr>
33-<tr>
34-<td><p>clBackground</p></td>
35-<td><p>Desktop background color</p></td>
36-<td><p>windowBackgroundColor</p></td>
37-<td><p>Returns a pattern color that will draw the ruled lines for the window background.</p></td>
38-</tr>
39-<tr>
40-<td><p>clActiveCaption</p></td>
41-<td><p>Active window titlebar</p></td>
42-<td><p>windowFrameColor</p></td>
43-<td><p>Returns the system color used for window frames, except for their text.</p></td>
44-</tr>
45-<tr>
46-<td><p>clInactiveCaption</p></td>
47-<td><p>Inactive window titlebar</p></td>
48-<td><p>windowBackgroundColor</p></td>
49-<td></td>
50-</tr>
51-<tr>
52-<td><p>clMenu</p></td>
53-<td><p>Regular menu item background color</p></td>
54-<td><p>controlBackgroundColor</p></td>
55-<td><p>Returns the system color used for the background of large controls.</p></td>
56-</tr>
57-<tr>
58-<td><p>clWindow</p></td>
59-<td><p>The normal background brush of unselected text. Defined for controls like TEdit, TComboBox, TMemo, TListBox, TTreeView.</p></td>
60-<td><p>textBackgroundColor</p></td>
61-<td><p>Returns the system color used for the text background.</p></td>
62-</tr>
63-<tr>
64-<td><p>clWindowFrame</p></td>
65-<td><p>Color of frame around the window</p></td>
66-<td><p>windowFrameColor</p></td>
67-<td></td>
68-</tr>
69-<tr>
70-<td><p>clMenuText</p></td>
71-<td><p>The font color to use together with clMenu</p></td>
72-<td><p>controlTextColor</p></td>
73-<td><p>Returns the system color used for text on controls that aren’t disabled.</p></td>
74-</tr>
75-<tr>
76-<td><p>clWindowText</p></td>
77-<td><p>Font color to use together with clWindow</p></td>
78-<td><p>controlTextColor</p></td>
79-<td></td>
80-</tr>
81-<tr>
82-<td><p>clCaptionText</p></td>
83-<td><p>Active window titlebar text color</p></td>
84-<td><p>windowFrameTextColor</p></td>
85-<td><p>Returns the system color used for the text in window frames.</p></td>
86-</tr>
87-<tr>
88-<td><p>clActiveBorder</p></td>
89-<td><p>?</p></td>
90-<td><p>windowFrameColor</p></td>
91-<td></td>
92-</tr>
93-<tr>
94-<td><p>clInactiveBorder</p></td>
95-<td><p>?</p></td>
96-<td><p>windowFrameColor</p></td>
97-<td></td>
98-</tr>
99-<tr>
100-<td><p>clAppWorkspace</p></td>
101-<td><p>MDIMain form background</p></td>
102-<td><p>windowBackgroundColor</p></td>
103-<td></td>
104-</tr>
105-<tr>
106-<td><p>clHighlight</p></td>
107-<td><p>The brush color of selected element</p></td>
108-<td><p>selectedControlColor</p></td>
109-<td><p>Returns the system color used for the face of a selected control—a control that has been clicked or is being dragged.</p></td>
110-</tr>
111-<tr>
112-<td><p>clHighlightText</p></td>
113-<td><p>Font color of selected text (to use together with clHighligh).</p></td>
114-<td><p>selectedControlTextColor</p></td>
115-<td><p>Returns the system color used for text in a selected control—a control being clicked or dragged.</p></td>
116-</tr>
117-<tr>
118-<td><p>clBtnFace</p></td>
119-<td><p>Button background</p></td>
120-<td><p>controlColor</p></td>
121-<td><p>Returns the system color used for the flat surfaces of a control.</p></td>
122-</tr>
123-<tr>
124-<td><p>clBtnShadow</p></td>
125-<td><p>Button shadow color (bottom right) used to achieve 3D effect</p></td>
126-<td><p>controlShadowColor</p></td>
127-<td><p>Returns the system color used for the shadows dropped from controls.</p></td>
128-</tr>
129-<tr>
130-<td><p>clGrayText</p></td>
131-<td><p>The font color of disabled element</p></td>
132-<td><p>disabledControlTextColor</p></td>
133-<td><p>Returns the system color used for text on disabled controls.</p></td>
134-</tr>
135-<tr>
136-<td><p>clBtnText</p></td>
137-<td><p>Button font color to use together with clBtnFace</p></td>
138-<td><p>controlTextColor</p></td>
139-<td></td>
140-</tr>
141-<tr>
142-<td><p>clInactiveCaptionText</p></td>
143-<td><p>Inactive window titlebar text color</p></td>
144-<td><p>windowFrameTextColor</p></td>
145-<td></td>
146-</tr>
147-<tr>
148-<td><p>clBtnHighlight</p></td>
149-<td><p>Button highlight color (top left) used to achieve 3D effect</p></td>
150-<td><p>controlLightHighlightColor</p></td>
151-<td><p>Returns the system color used for light highlights in controls.</p></td>
152-</tr>
153-<tr>
154-<td><p>cl3DDkShadow</p></td>
155-<td><p>?</p></td>
156-<td><p>controlDarkShadowColor</p></td>
157-<td><p>Returns the system color used for the dark edge of the shadow dropped from controls.</p></td>
158-</tr>
159-<tr>
160-<td><p>cl3DLight</p></td>
161-<td><p>?</p></td>
162-<td><p>controlHighlightColor</p></td>
163-<td><p>Returns the system color used for the highlighted bezels of controls.</p></td>
164-</tr>
165-<tr>
166-<td><p>clInfoText</p></td>
167-<td><p>Font color for hints. Use together with clInfoBk</p></td>
168-<td><p>controlTextColor</p></td>
169-<td></td>
170-</tr>
171-<tr>
172-<td><p>clInfoBk</p></td>
173-<td><p>Brush color for hints. Use together with clInfoText</p></td>
174-<td><p><em>hard coded</em></p></td>
175-<td><p>The actual color value depends on MacOS version. Before macOS 10.10 (Yosemite) the color is yellowish. on 10.10 and after, the color is gray. The change follows Apple system hint color change. The API to identify hint window color is unknown.</p>
176-<p>CocoaInt unit also provides a global variable CocoaHintColor. The value is used to return value for clInfoBk. Thus if Apple changes the design in future, you can always adjust hint color from your code.</p></td>
177-</tr>
178-<tr>
179-<td><p>clHotLight</p></td>
180-<td><p>?</p></td>
181-<td><p>alternateSelectedControlColor</p></td>
182-<td><p>Returns the system color used for the face of a selected control in a list or table.</p></td>
183-</tr>
184-<tr>
185-<td><p>clGradientActiveCaption</p></td>
186-<td><p>The second color used to make gradient of active window titlebar</p></td>
187-<td><p>windowFrameColor</p></td>
188-<td></td>
189-</tr>
190-<tr>
191-<td><p>clGradientInactiveCaption</p></td>
192-<td><p>The second color used to make gradient for inactive window titlebar</p></td>
193-<td><p>windowBackgroundColor</p></td>
194-<td></td>
195-</tr>
196-<tr>
197-<td><p>clMenuHighlight</p></td>
198-<td><p>The background color of selected menu item</p></td>
199-<td><p>selectedMenuItemColor</p></td>
200-<td><p>Returns the system color used for the face of selected menu items. (depreciated in macOS 10.14)</p></td>
201-</tr>
202-<tr>
203-<td><p>clMenuBar</p></td>
204-<td><p>The Backround color of menu bar</p></td>
205-<td><p>selectedTextBackgroundColor</p></td>
206-<td><p>Returns the system color used for the background of selected text.</p></td>
207-</tr>
208-<tr>
209-<td><p>clForm</p></td>
210-<td><p>?</p></td>
211-<td><p>windowBackgroundColor</p></td>
212-<td></td>
213-</tr>
214-<tr>
215-<td><p>clColorDesktop</p></td>
216-<td><p>?</p></td>
217-<td></td>
218-<td></td>
219-</tr>
220-<tr>
221-<td><p>cl3DFace</p></td>
222-<td><p>?</p></td>
223-<td></td>
224-<td></td>
225-</tr>
226-<tr>
227-<td><p>cl3DShadow</p></td>
228-<td><p>?</p></td>
229-<td></td>
230-<td></td>
231-</tr>
232-<tr>
233-<td><p>cl3DHiLight</p></td>
234-<td><p>?</p></td>
235-<td></td>
236-<td></td>
237-</tr>
238-<tr>
239-<td><p>clBtnHiLight</p></td>
240-<td><p>Same as clBtnHighlight</p></td>
241-<td></td>
242-<td></td>
243-</tr>
244-</tbody>
245-</table>
17+**Constant**
24618
19+**LCL definition**
20+
21+**NSColor**
22+
23+**[Cocoa definition](https://developer.apple.com/documentation/appkit/nscolor?language=objc)**
24+
25+clScrollBar
26+
27+Scrollbar body
28+
29+scrollBarColor
30+
31+Returns the system color used for scroll “bars”—that is, for the groove in which a scroller’s knob moves
32+
33+clBackground
34+
35+Desktop background color
36+
37+windowBackgroundColor
38+
39+Returns a pattern color that will draw the ruled lines for the window background.
40+
41+clActiveCaption
42+
43+Active window titlebar
44+
45+windowFrameColor
46+
47+Returns the system color used for window frames, except for their text.
48+
49+clInactiveCaption
50+
51+Inactive window titlebar
52+
53+windowBackgroundColor
54+
55+clMenu
56+
57+Regular menu item background color
58+
59+controlBackgroundColor
60+
61+Returns the system color used for the background of large controls.
62+
63+clWindow
64+
65+The normal background brush of unselected text. Defined for controls like TEdit, TComboBox, TMemo, TListBox, TTreeView.
66+
67+textBackgroundColor
68+
69+Returns the system color used for the text background.
70+
71+clWindowFrame
72+
73+Color of frame around the window
74+
75+windowFrameColor
76+
77+clMenuText
78+
79+The font color to use together with clMenu
80+
81+controlTextColor
82+
83+Returns the system color used for text on controls that aren’t disabled.
84+
85+clWindowText
86+
87+Font color to use together with clWindow
88+
89+controlTextColor
90+
91+clCaptionText
92+
93+Active window titlebar text color
94+
95+windowFrameTextColor
96+
97+Returns the system color used for the text in window frames.
98+
99+clActiveBorder
100+
101+?
102+
103+windowFrameColor
104+
105+clInactiveBorder
106+
107+?
108+
109+windowFrameColor
110+
111+clAppWorkspace
112+
113+MDIMain form background
114+
115+windowBackgroundColor
116+
117+clHighlight
118+
119+The brush color of selected element
120+
121+selectedControlColor
122+
123+Returns the system color used for the face of a selected control—a control that has been clicked or is being dragged.
124+
125+clHighlightText
126+
127+Font color of selected text (to use together with clHighligh).
128+
129+selectedControlTextColor
130+
131+Returns the system color used for text in a selected control—a control being clicked or dragged.
132+
133+clBtnFace
134+
135+Button background
136+
137+controlColor
138+
139+Returns the system color used for the flat surfaces of a control.
140+
141+clBtnShadow
142+
143+Button shadow color (bottom right) used to achieve 3D effect
144+
145+controlShadowColor
146+
147+Returns the system color used for the shadows dropped from controls.
148+
149+clGrayText
150+
151+The font color of disabled element
152+
153+disabledControlTextColor
154+
155+Returns the system color used for text on disabled controls.
156+
157+clBtnText
158+
159+Button font color to use together with clBtnFace
160+
161+controlTextColor
162+
163+clInactiveCaptionText
164+
165+Inactive window titlebar text color
166+
167+windowFrameTextColor
168+
169+clBtnHighlight
170+
171+Button highlight color (top left) used to achieve 3D effect
172+
173+controlLightHighlightColor
174+
175+Returns the system color used for light highlights in controls.
176+
177+cl3DDkShadow
178+
179+?
180+
181+controlDarkShadowColor
182+
183+Returns the system color used for the dark edge of the shadow dropped from controls.
184+
185+cl3DLight
186+
187+?
188+
189+controlHighlightColor
190+
191+Returns the system color used for the highlighted bezels of controls.
192+
193+clInfoText
194+
195+Font color for hints. Use together with clInfoBk
196+
197+controlTextColor
198+
199+clInfoBk
200+
201+Brush color for hints. Use together with clInfoText
202+
203+*hard coded*
204+
205+The actual color value depends on MacOS version. Before macOS 10.10 (Yosemite) the color is yellowish. on 10.10 and after, the color is gray. The change follows Apple system hint color change. The API to identify hint window color is unknown.
206+
207+CocoaInt unit also provides a global variable CocoaHintColor. The value is used to return value for clInfoBk. Thus if Apple changes the design in future, you can always adjust hint color from your code.
208+
209+clHotLight
210+
211+?
212+
213+alternateSelectedControlColor
214+
215+Returns the system color used for the face of a selected control in a list or table.
216+
217+clGradientActiveCaption
218+
219+The second color used to make gradient of active window titlebar
220+
221+windowFrameColor
222+
223+clGradientInactiveCaption
224+
225+The second color used to make gradient for inactive window titlebar
226+
227+windowBackgroundColor
228+
229+clMenuHighlight
230+
231+The background color of selected menu item
232+
233+selectedMenuItemColor
234+
235+Returns the system color used for the face of selected menu items. (depreciated in macOS 10.14)
236+
237+clMenuBar
238+
239+The Backround color of menu bar
240+
241+selectedTextBackgroundColor
242+
243+Returns the system color used for the background of selected text.
244+
245+clForm
246+
247+?
248+
249+windowBackgroundColor
250+
251+clColorDesktop
252+
253+?
254+
255+cl3DFace
256+
257+?
258+
259+cl3DShadow
260+
261+?
262+
263+cl3DHiLight
264+
265+?
266+
267+clBtnHiLight
268+
269+Same as clBtnHighlight
270+
247271For Reference: [Apple Human Interface Guidelines - Dynamic System Colors](https://developer.apple.com/design/human-interface-guidelines/macos/visual-design/color/#dynamic-system-colors)
248272
249273### Hint Window
250274
251275Cocoa provides its own API to show a popup hint window. Thus Cocoa doesn't provide must information on how hint popup window should actually be shown.
252276
253277On dark theme of Mojave system, it became a bit more complicated. Besides a different fill color for darktheme, the popup window also draws a border of light pixels. ![](/wiki-images/2/2f/Mojave-DarkLight-Tooltip.png)
254278
255279## Fonts
256280
257281Historically, MacOS (Classic MacOS, Mac OS X, and macOS) systems are using **72** ppi (or dpi). Windows is using **96** dpi (so do Linux desktop managers).
258282
259283### Default
260284
261285NSFont class provides a number of class methods to get proper system font without selecting the font by name. The same of getting system-native font size.
262286
263287### 96 DPI
264288
265289macOS native DPI (aka PPI) is 72 (it matches the basic typographic resolution).
266290
267291For comparison: Windows native DPI is 96. You can read more about history of this difference [here](https://en.wikipedia.org/wiki/Dots_per_inch#Computer_monitor_DPI_standards)
268292
269293In order to achieve the ease of use and design for cross-platform applications, Cocoa (screen) DPI is also emulated (by LCL) to be at 96 dpi. What that actually means is that font sizes between LCL applications and macOS native applications will be different (at roughly 33%).
270294
271-<figure>
272-<img src="CarbonFontWrong.png" title="CarbonFontWrong.png" />
273-<figcaption>CarbonFontWrong.png</figcaption>
274-</figure>
295+![](/wiki-images/6/6b/CarbonFontWrong.png)
275296
276297This can be adjusted by changing the **CocoaBasePPI** variable at run time.
277298
278299### Font Enumeration
279300
280301To implement windows-like font enumeration, two NSFontManager methods are used
281302
282303
283304**availableFontFamilies** - to get the list of families
284305
285306**availableMembersOfFontFamily:** - to get the list of available styles for fonts
286307
287308Input parameters recognized:
288309
289310- todo: **lfFaceName** - the case-insensitive, exact name match.
290311-
291312
292313## Handles
293314
294315The following objects are used to implement HANDLEs for graphical objects
295316
296-<table>
297-<thead>
298-<tr>
299-<th><p>LCL Handle</p></th>
300-<th><p>Cocoa WS Class</p></th>
301-<th><p>Notes</p></th>
302-</tr>
303-</thead>
304-<tbody>
305-<tr>
306-<td><p>HICON</p></td>
307-<td><p>TCocoaBitmap</p></td>
308-<td></td>
309-</tr>
310-<tr>
311-<td><p>HPEN</p></td>
312-<td><p>TCocoaPen</p></td>
313-<td></td>
314-</tr>
315-<tr>
316-<td><p>HBRUSH</p></td>
317-<td><p>TCocoaBrush</p></td>
318-<td></td>
319-</tr>
320-<tr>
321-<td><p>HRGN</p></td>
322-<td><p>TCocoaRegion</p></td>
323-<td></td>
324-</tr>
325-<tr>
326-<td><p>HCURSOR</p></td>
327-<td><p>TCocoaCursor</p></td>
328-<td><p>TCocoaCursor doesn't inherit from TCocoaBitmap)</p></td>
329-</tr>
330-<tr>
331-<td><p>HBITMAP</p></td>
332-<td><p>TCocoaBitmap</p></td>
333-<td></td>
334-</tr>
335-<tr>
336-<td><p>TBitmap.Canvas.Handle</p></td>
337-<td><p>TCocoaBitmapContext</p></td>
338-<td><p>The key difference from TCocoaContext is that after any changes to bitmap context, the underlying image itself is invalidated.</p>
339-<p>This is necessary for Windows like behavior. (macOS image objects are immutable, but windows bitmaps are)</p></td>
340-</tr>
341-<tr>
342-<td><p>TControl.Canvas.Handle</p></td>
343-<td><p>TCocoaContext</p></td>
344-<td></td>
345-</tr>
346-</tbody>
347-</table>
317+**LCL Handle**
348318
319+**Cocoa WS Class**
320+
321+**Notes**
322+
323+HICON
324+
325+TCocoaBitmap
326+
327+HPEN
328+
329+TCocoaPen
330+
331+HBRUSH
332+
333+TCocoaBrush
334+
335+HRGN
336+
337+TCocoaRegion
338+
339+HCURSOR
340+
341+TCocoaCursor
342+
343+TCocoaCursor doesn't inherit from TCocoaBitmap)
344+
345+HBITMAP
346+
347+TCocoaBitmap
348+
349+TBitmap.Canvas.Handle
350+
351+TCocoaBitmapContext
352+
353+The key difference from TCocoaContext is that after any changes to bitmap context, the underlying image itself is invalidated.
354+
355+This is necessary for Windows like behavior. (macOS image objects are immutable, but windows bitmaps are)
356+
357+TControl.Canvas.Handle
358+
359+TCocoaContext
360+
349361## Bitmap
350362
351363**TCocoaBitmap** implements the internal bitmap handle.
352364
353365### Change Tracking
354366
355367In order for a bitmap (a 2d-array of pixel values) to be drawn, a NSBitmapImageRep object.
356368
357369The NSBitmapImageRep is immutable. Its contents cannot be changed after the initial drawing (the pixel values seems it be copied within Cocoa).
358370
359371If a Bitmap contents was modified (i.e. by using (Canvas) Drawing methods or by direct access via ScanLine), the bitmap must re-create NSBitmapImageRep before the next drawing.
360372
361373The SetModified() marks the Bitmap as modified. TCocoaBitmapContext (Device Context created for a Bitmap) would mark the bitmap as modified on any draw method.
362374
363375### Scan Lines
364376
365377For PixelFormat 32-bit the pixel format is as following:
366378
367379`$BBGGRRAA`\
368380`$ff0000ff - all blue`\
369381`$00ff00ff - all green`\
370382`$0000ffff - all red`\
371383`$000000ff - all black (alpha channel only)`\
372384`$ffffff00 - fully transparent`
373385
374386## Forced Repaint
375387
376388There's an additional code added for processing **DrawRect** event. If a control was resized during a draw rect, then the resulting graphics output could be corrupted. [32970](https://bugs.freepascal.org/view.php?id=32970)
377389
378390As an example TTreeView component could be used. It updates scroll bars during the initial paint. The update of scroll bars is causing a client rectangle to be changed, causing a glitch when drawing the control for the first time
379391
380392Naturally, the next repaint fixes the problem right away.
381393
382394![](/wiki-images/7/7c/CocoaInvalidTree.png) ![](/wiki-images/d/db/CocoaValidTree.png)
383395
384396Sending another event into Cocoa event queue, to repaint the control again would cause flickering and yet bad user experience. Forcefully calling for a repaint one more time seems to be resolving the problem, while potentially is an overhead due to double job done.
385397
386398Also double drawing could cause artifacts on controls that are using any sorts of transparency:
387399
388-<figure>
389-<img src="TransperancyDoubleDraw.png" title="TransperancyDoubleDraw.png" />
390-<figcaption>TransperancyDoubleDraw.png</figcaption>
391-</figure>
400+![](/wiki-images/e/e7/TransperancyDoubleDraw.png)
392401
393402The best solution is to avoid changing of the control bounds at all during drawing operation.
394403
395404## Theme Drawing
396405
397406HITheme API is deprecated by Apple together with Carbon. It's still available in OS X, but for i386 only. It will presumably be completely removed on 64-bit only macOS.
398407
399408However, some LCL controls cannot be mapped to existing Cocoa provided controls and thus might require some "custom drawing". The drawing should look system native though. In order to achieve that the NSCell family could be used. NSCell allows drawing (hit-test and as well as handle user input) for OS X native elements. If Apple changes the appearance of controls (cells), the LCL application would "pick-up" the look automatically.
400409
401410**Deprecated? macOS version specific?** In order to be drawn NSCells require the presence of NSView, thus it's hard to use them for the implementation of LCL TTheme APIs. NSView doesn't seem to be required. At least NSCell operates without the presence NSView. However, per Apple's documentation it's mentioned that the drawing would occur in a "focused" control. That helps to use NSCell for on-screen drawing, but is a big question for bitmap drawing.
402411
403412Example of NSCell usage is CocoaStatusBar drawing.
404413
405414It might be that Apple moves away from using NSCell. The class itself is not yet deprecated, even though Apple suggests that NSView should be used more extensively.
406415
407416## See Also
408417
409418- [[Cocoa Internals]]
410419- [Introduction to Color Programming Topics for Cocoa](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/DrawColor/DrawColor.html)
411420
412421---
413422*From the Free Pascal wiki, page "Cocoa Internals/Graphics", as it stood on 2022-05-31 after a change by Skalogryz, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).*
414423Category: Cocoa
415424Category: macOS

Back to history