Is there a Mac OSX version of windows GetFontData function? - c++

We have an application that allows our users to generate print-ready PDF documents using variable data (names, titles, phone numbers, etc) that their customer's enter via an online e-commerce website. To facilitate the variable data we have to embed a font's entire character map. On windows we have been using the windows API function GetFontData(...) like so:
#ifdef Q_WS_WIN
//this is windows specific code
HDC DC = CreateCompatibleDC(NULL);
HFONT hFont = font.handle();
HFONT oFont=(HFONT)SelectObject(DC,hFont);
DWORD fontLength = ::GetFontData(DC, 0, 0, 0, 0);
if(fontLength != GDI_ERROR)
{
fontData.GrowAllocation(fontLength);
if(::GetFontData(DC, 0, 0, fontData.GetBuffer(), fontLength) == GDI_ERROR)
{
fontData.Clear();
}
else
{
fontData.SetLength(fontLength);
returnVal = true;
}
}
SelectObject(DC,oFont);
DeleteDC(DC);
//End of windows specific code
#elif defined(Q_WS_MAC)
#endif
This technique works very successfully on our windows specific version; however, we are porting the application to Qt to target the Mac OSX platform.
My first question: Is there a Qt way of accessing the raw font data from a QFont, QFontDatabase, etc. that we could use to embed in the pdf? We have been unable to find a way. Notice the #ifdef wrapper in the above code. Note that the variable fontData is a self contained memory buffer that manages its own memory, please disregard.
My second question: If there is no Qt way of accessing the font data in an OS agnostic way, what is the OSX equivalent to the windows GetFontData?
Thanks

I've only skimmed documentation for GetFontData, and I don't know much about Qt (though it does sound like a Qt solution would be preferable), but you might want to look at the ObjC class for fonts, NSFont.

The latest (until Apple hires new font people and gets infected with not-invented-here disease again) text and font API is Core Text. I never used it since chasing Apple's mood is harmful to my personal and organization's financial health, I stopped using any Apple-only API. :)
Kidding aside, it looks like CTFont does provide access to all tables in a font. I don't see anything that prepares a font for embedding but this probably gives you the best chance.

Related

How to load multiple font of same familiy

I am writing an application using the Qt framework. In the display, I have to show multiple information, but using different types of font of the same family, Montserrat.
What I have done so far to load the fonts is:
int ultralightid = QFontDatabase::addApplicationFont(":/Montserrat_UltraLight.tff");
QString UltraFont= QFontDatabase::applicationFontFamilies(ultralightid ).at(0);
QFont font1(UltraFont,QFont::Normal);
font1.setPixelSize(50);
int lightid = QFontDatabase::addApplicationFont(":/Montserrat_Light.tff");
QString LightFont= QFontDatabase::applicationFontFamilies(lightid).at(0);
QFont font2(LightFont,QFont::Normal);
font2.setPixelSize(150);
label1->setFont(font1);
label2->setFont(font2);
label1->setText("bla bla");
label2->setText("bla bla");
The font sizes are correct, but the font itself it is not. From what I have noticed (trying with Hairline_Montserrat,Light_Montserrat,UltraLight_Montserrat), it is as if the fonts have a sort of priority. If I declare them all, all the fonts are the Light one, if I comment that font type, all of them are Hairline one, otherwise (last priority) the labels use the ultralight font.
I have tried adding other font type (from other families) and in that case my code works correctly.
If I use
qDebug()<<QFontDatabase::applicationFontFamilies(ultralightid);
qDebug()<<QFontDatabase::applicationFontFamilies(lightid);
both of them print the family "Montserrat".
I use the qrc file and the AUTORCC flag in the CMAKE (it should be similar using qmake) and all the file are uploaded correctly.
Do you know if there is another way to add fonts of the same family? Or is there something I am doing wrong?
Here are the fonts:
https://www.onlinewebfonts.com/download/9d31c906a6cc6064bbe7d33d51058317 light
https://it.allfont.net/download/montserrat-light/ ultralight
This is an old question but I was just struggling with exactly the same problem when trying to load normal, bold, ... versions of a font family in Qt.
I solved the problem (although in a somewhat hacky way) by simply giving each of the ttf files a different family name. I used Typograf, simply open the font, right click to open properties and then click rename. There are probably many other tools that do this too.
You don't need to manage font files from one family separatelly.
I suggest this solution:
Create a folder with all ttf's of the same family.
Load all files from the folder via id = QFontDatabase.addApplicationFont(path)
Collect all font families from these files via QFontDatabase.applicationFontFamilies(id)
Check if only one and desired family is loaded, and the family name is exactly the same as requested, or warn the user about these errors.
Create font object font = QFont(family)
Then for example, font.setItalic(True). If Italic version of family is loaded, it will be used, otherwise it will be created from Regular by QT.

Create window without title bar

I am trying to create a simple panel for Openbox in Arch Linux using c++, but I cannot figure out how to remove the title bar from a window.
I am creating the window with XCreateWindow(...), and that gives a window with the correct size, but it contains a title bar, and the window also opens in the top-left corner of the screen, no matter what offset coordinates I specify.
I read here that both of these problems are probably caused by the window manager (Openbox), which overrides the window attributes I specified in XCreateWindow(..., &window_attributes). This could be solved by adding window_attributes.override_redirect = True;, although this does not seem to do anything for me. When I try this I get the exact same window as before. (I did compile the file after this change.)
Also I read into the code of Tint2 (link), which is another panel for Openbox. They create a window using the following code:
XSetWindowAttributes att = { .colormap=server.colormap, .background_pixel=0, .border_pixel=0 };
p->main_win = XCreateWindow(server.dsp, server.root_win, p->posx, p->posy, p->area.width, p->area.height, 0, server.depth, InputOutput, server.visual, mask, &att);
I don't see an override_redirect anywhere in their code, so I'm not sure how they are removing the title bar.
As additional information, I thought it would be worth mentioning how I'm executing the script:
/* The c++ file is saved as 'panel.cpp' */
$ gcc panel.cpp -lX11 -o panel
$ ./panel
Also, I am running Arch Linux through VirtualBox with Windows 8 as host. I'm not sure if this changes anything, but it won't hurt to mention.
Since I found the solution, I figured I'd post the solution here if anyone else needs it.
As #JoachimPileborg mentioned, I needed to alter the Openbox settings in ~/.config/openbox/rc.xml. Inside the <applications> tag, I added the following code:
<application class="*">
<decor>no</decor>
<position force="no"></position>
</application>
The class="*" means that all applications will follow these rules, you could fill in the class name of the application instead. The <decor>no</decor> removes the title bar, and <position force="no"></position> ensures that my own script is able to handle the positioning. You could also add another <application> tag after this one to make exceptions to this rule.
Also, the window_attributes.override_redirect = True; is not needed anymore.
A more correct way is to use the Extended Window Manager Hints.
The idea is that you don't tell the window manager how to decorate or not your window, you just indicate the window type with _NET_WM_WINDOW_TYPE :
Atom window_type = XInternAtom(display, "_NET_WM_WINDOW_TYPE", False);
long value = XInternAtom(display, "_NET_WM_WINDOW_TYPE_DOCK", False);
XChangeProperty(display, your_window, window_type,
XA_ATOM, 32, PropModeReplace, (unsigned char *) &value,1 );
"Dock" is the type for panels and taskbar. Usually they are undecorated and appear on all desktops. As written on the documentation, previously the _MOTIF_WM_HINTS property was used to define the appearance and decorations of the window. Window managers still support it, but _NET_WM_WINDOW_TYPE is prefered as it describe the function and let the window manager (and user) decide on the appearance and behavior of that type of window.
Another interesting property for a panel is _NET_WM_STRUT_PARTIAL, to "reserve" space.

linux, C++, xft : how to use it?

I try to use Xft, the tutorial, well let them calling that a tutorial... looks like it was written in a north korean camp... I also found this one. So let me try to do a step-by-step :
// g++ XftTest.cc -lX11 -lXft `pkg-config --cflags freetype2`
#include<unistd.h>
#include<X11/Xlib.h>
#include<X11/Xutil.h>
#include<X11/Xft/Xft.h>
int main()
{
Display *display;
XftFont *font;
XftDraw *xftdraw;
XRenderColor xrcolor;
XftColor xftcolor;
display = XOpenDisplay(0);
Window XP = XCreateSimpleWindow(display,DefaultRootWindow(display),0,0,360,90,0,0,0);
XMapWindow(display,XP);
font = NULL; /* added 6/16 */
//font = XftFontOpenName(display,0,"NorthKorea-50"); // how to check if this is good ?
font = XftFontOpenName(display,0,"") /* added 6/16 */
if (!font) return 1;
xftdraw = XftDrawCreate(display,XP,DefaultVisual(display,0),DefaultColormap(display,0));
xrcolor.red =65535;
xrcolor.green=0;
xrcolor.blue =0;
xrcolor.alpha=65535;
XftColorAllocValue(display,DefaultVisual(display,0),DefaultColormap(display,0),&xrcolor,&xftcolor);
XftDrawString8(xftdraw, &xftcolor, font, 20,70 , (XftChar8 *)"Joe Dalton", 10);
XFlush(display);
sleep(2);
XftDrawDestroy(xftdraw);
XftColorFree(display,DefaultVisual(display,0),DefaultColormap(display,0),&xftcolor);
return 0;
}
as you can see, in the XftFontOpenName :
XftFontOpenName(display,0,"NorthKorea-50")
if you write a bullshit, like I did, there is no error or something to tell me that I don't have a font called NorthKorea. That make sense since XftFontOpenName returns the nearest font from the string.
So, how can I check if my font match or not ? how can I use a font like arial? I tried XftFontOpenName(display,0,"arial-50"), I got nothing different.
On my system, I have these folders in my fonts folder :
$ls /usr/share/fonts/
100dpi 75dpi cyrillic encodings misc OTF TTF Type1 util
can I use any font in these folders by the same way ?
if you guys have some nice internet links, it would be a pleasure for me to take a look.
n.b. : there is no xft tag...
update 6/16
I'm still stuck with dat stuff...
I don't understand, if I replace
font = XftFontOpenName(display,0,"NorthKorea-50");
by
font = XftFontOpenName(display,0,"");
it still loading a font...
xlsfonts return a lot of stuff, like dat one :
-monotype-courier new-bold-r-normal--0-0-0-0-m-0-iso8859-10
but passing this as argument to XftFontOpenName changes nothing; I try to load a font with XftFontOpenXlfd too, it returns always NULL...
xft uses fontconfig for font discovery. xlsfonts is a way to query the old X core fonts system fontconfig replaced. xlsfonts results won't map in any reliable way way to the fontconfig state.
So:
forget about any shortcut where xft work sort-of like the X core font system documented in last centuries tech books. It is completely different. It is not X core fonts with antialiasing and truetype support. It is something that can use modern fonts and do antialiasing, but definitely not X core fonts in any form
Read the fontconfig documentation, the fontconfig configuration files on your system, and use fontconfig utilities (fc-query, fc-list, etc) to query the fontconfig state
as the people who maintain xorg (both x core fonts and fontconfig) already told you, do not try to use xft directly. xft is the product of the first attempt to write a new font stack. Its capabilities are not sufficient to manage modern text and modern fonts. The part dealing with modern font format complexities has been spun out in pango a long time ago (because it was proving complex enough it deserved a separate project). If you try to use xft alone, you'll hit the deficiencies in pre-pango code sooner or later, and no one will be interested in fixing your problems because the same code has already been subjected to a decade of fixes pango-side. Avoiding pango is not a shortcut. Avoiding pango is trying to rely of an half-finished, abandonned for years project.
forget about matching a specific font file. fontconfig will actively fight any attempt to work this way. In the post-core-fonts world, you give the font system a font pattern, and it will build a matching font for you. If the result is not the font file you expected that's because the file was evaluated and found lacking. If you want fontconfig to use this file you will have to fix the font file (add the missing glyphs, the missing font styles, etc), not write code to try to force it anyway. Fontconfig considers that it's more important to render a text your users can read, than to only render the parts your pet font can do. And yes that's now how you're used to think about it on other systems. fontconfig is different. Nothing short of a rewrite will make it behave like you expect. No one is interested in this rewrite because by and large fontconfig has been quite successful those past years.
fonts opentype text-rendering fontconfig linux
You should not pass an empty string to XftFontOpenName and expect to match a font. Xft provides support for core fonts and the structure nested within XftFont is a union of XFontStruct and XftFontStruct. X11 fills in the default font in the XFontStruct when creating new instances, so in the case of empty string you are likely getting the default core font.
In the simplest approach, one can hard code a font name like this:
const char *font_name = "Arial-20";
XftFont *font = XftFontOpenName (display, DefaultScreen(display), font_name);
Or you could use XftFontMatch and check the "results" before passing the pattern to XftFontOpenPattern. See http://keithp.com/~keithp/talks/xtc2001/paper/xft.html#sec-editing
Note that XCloseDisplay is missing.

Setting wxTE_PASSWORD later

I created two wxTextCtrl. One for log in (loginTxt) and another for password (pwdTxt) and both have readable default message.
I also installed wxEVT_LEFT_DOWN event so that when user click on either loginTxt or pwdTxt the default message will be set to empty string
Is it possible to set wxTE_PASSWORD style to the pwdTxt later? If it's possible, how can I do that?
I read wx.chm and it say,
"Note that alignment styles (wxTE_LEFT, wxTE_CENTRE and wxTE_RIGHT) can be changed dynamically after control creation on wxMSW and wxGTK. wxTE_READONLY, wxTE_PASSWORD and wrapping styles can be dynamically changed under wxGTK but not wxMSW. The other styles can be only set during control creation.".
I am writing my application on MS Windows with wxWidgets 2.9.3
You cannot change it later on Windows, since Microsoft's control does not support that. If you really need to, I suggest creating 2 different controls and show/hide the appropriate one.
Windows-only solution, probably will be useful:
void Sample::OnBUTTONClick( wxCommandEvent& event )
{
#if defined(__WXMSW__)
HWND hWnd = (HWND)m_Text->GetHandle();
SendMessage(hWnd, EM_SETPASSWORDCHAR, 0x25cf, 0); // 0x25cf is ● character
m_Text->Update();
#endif
}

Programming with Qt creator and Cocoa ( copying the selected text from the current application)

I would like to know if there is a way to use the Cocoa API in a Qt application.
I've already used the Windows API to get the selected text from the active application.
I'd like to do the same with mac os.
I tried to make a simple "hello world" application C++ with xCode, including the <Cocoa/Cocoa.h> but it didn't work as I excepted.
Is there a way to get this "hello word" application to build with Cocoa?
And, also If that is possible, can I get the selected text from the active windows with Cocoa API?
EDIT :
All right, so I successfully build something using Cocoa.h, thanks to this thread : How to mix Qt, C++ and Obj-C/Cocoa.
For the selection problem you could check out the answers I posted which tell you how to do it.
For those who could be interested : I found a way to get the current selected text.
Just by simulating cmd + c :
So thanks to this thread, I changed the code to obtain the "c" key which is represented by the integer 8 (Found in NSEvent.h), so here's the code :
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateCombinedSessionState);
CGEventRef saveCommandDown = CGEventCreateKeyboardEvent(source, (CGKeyCode)8, YES);
CGEventSetFlags(saveCommandDown, kCGEventFlagMaskCommand);
CGEventRef saveCommandUp = CGEventCreateKeyboardEvent(source, (CGKeyCode)8, NO);
CGEventPost(kCGAnnotatedSessionEventTap, saveCommandDown);
CGEventPost(kCGAnnotatedSessionEventTap, saveCommandUp);
CFRelease(saveCommandUp);
CFRelease(saveCommandDown);
CFRelease(source);
Now you just have to access the clipboard from Qt to get the selection. (If ask, I can put the code to do so)
Anyway, thanks to the stackoverflow community ;)