How to detect missing font characters - c++

Is there a way to detect that all characters are displayed properly with the current font? In some environments and fonts certain characters are replaced with a square symbol.
I'd like to automatically verify that all characters used in the GUI are supported by the current font.

I found a possible solution using the QFontMetrics class. Here is a an example function to query whether all characters are available in the current text of a QLabel:
bool charactersMissing(const QLabel& label) {
QFontMetrics metrics(label.font());
for (int i = 0; i < label.text().size(); ++i) {
if (!metrics.inFont(label.text().at(i))) {
return true;
}
}
return false;
}
Of course displaying to the user which character is missing would be good, but of course that has to be done with a different font :)

According to this discussion, I don't think the sample code of QFontMetrics will work well.
https://bugreports.qt-project.org/browse/QTBUG-1732
The QFontMetrics inFont() function depend on QFont class, and it seems you have to set the StyleStrategy to QFont::NoFontMerging. But actually, the NoFontMerging flag doesn't work in that way you think, so the inFont function still return true if other fonts in your system have this glyph.
BTW, I make a verification tool in python finally.
https://github.com/diro/pyGlyphChecker

A possible solution...
Depending upon your application the following might be a possible solution
(or completetly not applicable) :
Popup a dialog-box with a sample paragraph containing all the characters that you intend to use.
Render the paragraph using the FONT u have in mind.
Display a message to the user to
-- Select OK (if he/she can read the text i.e. only if no "squares" visible)
-- Select a different FONT (if any "squares" are visible)
NOTE: In case you are wondering, this is not a very uncommon behaviour for apps. MS-WORD does this when it detects non-standard encoding in a doc file.
GoodLUCK!!

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.

MSHTML editing - changing the text selection color

I use MSHTML (TWebBrowser control) in Design (edit) mode. I use TEmbeddedWB but slowly moving away from that component and implementing my own interface. When a block of text is selected, so when typing into the editor and then selecting a block of text it is in black color for the background color.
Instead I'd like to use blue.
I know that it has something to do with the selection range but not sure how to modify it in designer mode. The code below is of course when it is not in design mode.
IHTMLSelectionObject currentSelection = document.selection;
IHTMLTxtRange range = currentSelection.createRange() as IHTMLTxtRange;
if (range != null)
{
range.execCommand("BackColor", false, "0000FF");
}
Any ideas? Do I have to use event sinking? Or maybe QueryCommandValue? I tried some things with HiliteColor without success yet (according to Mozilla documentation this is not supported by Internet Explorer).
I use C++ Builder or Delphi, but code example in any language is welcome, I can (probably) translate it.

Reordering MFC control IDs automatically

I've got a pretty old MFC application that's been touched by many people over the years (most of them probably not even CS guys) and it follows, what I like to call the "anarchy design pattern."
Anyway, one of the dialogs has a series of 56 vertical sliders and check boxes. However, there are additional sliders and checkboxes on the dialog as shown below.
Now, the problem is that the additional sliders and checkboxes take on IDs that are in sequence with the slider/checkbox series of the dialog. My task is to add more sliders and checkboxes to the series (in the blank space in the Slider Control group box) Unfortunately, since IDC_SLIDER57 through IDC_SLIDER61 are already in the dialog (same goes for the checkboxes), existing code, such as the snippet below will break:
pVSlider = (CSliderCtrl *)GetDlgItem(IDC_SLIDER1+i);
Is there a better way to modify the resource file without doing it manually? I've seen a third party tool called ResOrg that looks like it'll help do what I want, but the software is a bit pricey, especially since I'll only use it once. I guess I can give the demo a try, but the limitations might restrict me.
FYI, I'm using Visual C++ 6.0 (yes...I know, don't laugh, it's being forced upon me).
Instead of writing:
pVSlider = (CSliderCtrl *)GetDlgItem(IDC_SLIDER1+i);
you could write:
pVSlider = (CSliderCtrl *)GetDlgItem(GetSliderID(i));
where GetSlider is a function that returns the id of slider number i.
GetSlider function
int GetSliderID(int nslider)
{
static int sliderids[] = {IDC_SLIDER1, IDC_SLIDER2, IDC_SLIDER3, .... IDC_SLIDERn};
ASSERT(nslider < _countof(sliderids));
return sliderids[nslider];
}
With this method the IDC_SLIDERn symbols dont need to have sequential values.

QTextEdit change font of individual paragraph/block

Using a QTextEdit, I need to change the font attributes of each paragraph individually. This is similar to how many word processors change the font of a paragraph when the user select a style from a menu (not a specific formatting).
Ideally, I would like to apply a QTextCharFormat (or equivalent) to a block (paragraph) just before it is laid out and rendered, but I would prefer that no font attribute be actually inserted in the text, as I don't want this information in the file but I need to preserve any bold/italic/underline attributes that the user might have set to words within paragraphs (I intend to save the needed information in a QTextBlock::userData). However, I can't figure where I would need to insert a function to perform this task.
I figured I could not change the QTextCharFormat of a paragraph from either QTextBlock nor QTextCursor as this only applies to new blocks, it doesn't affect blocks with existing text.
I checked out QTextLayout but I don't think my answer is there.
I have been looking for a solution to this problem for a few days now. I would be really gracious for any pointer in the right direction.
I have years of experience with C++, but I'm somewhat new to Qt. Using Qt 4.8.
Edit:
I added emphasize (bold) above to an important part of what I'm trying to do. In other word, what I'd really like to do is be able to apply the font attributes to the block of text (perhaps a temporary copy) just before it is displayed. I'm totally comfortable with deriving and modifying (even reimplement) any class that I need to in order to achieve that goal, but I need to be pointed to the right direction as to what I actually need to change. As a last resort, I could also modify some Qt class directly if that is necessary for the task, but again would need to know what class I need to touch. I hope this is clearer. I find it difficult to explain this without being allowed to tell you what the application will do exactly.
[Required Libraries]
#include <QTextEdit> // not needed if using the designer
#include <QTextDocument>
#include <QTextBlock>
#include <QTextCursor>
[Strategy]
QTextDocument
I need it to manage the blocks. The function QTextDocument::findBlockByNumber is quite handy to locate the previous blocks, and I think it is what you are after.
QTextBlock
Container for block texts. A nice and handy class.
QTextCursor
Surprisingly, there is no format-setter in QTextBlock class. Therefore I use QTextCursor as a workaround since there are four format-setters in this class.
[Code for formatting]
// For block management
QTextDocument *doc = new QTextDocument(this);
ui->textEdit->setDocument(doc); // from QTextEdit created by the Designer
//-------------------------------------------------
// Locate the 1st block
QTextBlock block = doc->findBlockByNumber(0);
// Initiate a copy of cursor on the block
// Notice: it won't change any cursor behavior of the text editor, since it
// just another copy of cursor, and it's "invisible" from the editor.
QTextCursor cursor(block);
// Set background color
QTextBlockFormat blockFormat = cursor.blockFormat();
blockFormat.setBackground(QColor(Qt::yellow));
cursor.setBlockFormat(blockFormat);
// Set font
for (QTextBlock::iterator it = cursor.block().begin(); !(it.atEnd()); ++it)
{
QTextCharFormat charFormat = it.fragment().charFormat();
charFormat.setFont(QFont("Times", 15, QFont::Bold));
QTextCursor tempCursor = cursor;
tempCursor.setPosition(it.fragment().position());
tempCursor.setPosition(it.fragment().position() + it.fragment().length(), QTextCursor::KeepAnchor);
tempCursor.setCharFormat(charFormat);
}
Reference:
How to change current line format in QTextEdit without selection?
[DEMO]
Building Environment: Qt 4.8 + MSVC2010 compiler + Windows 7 32 bit
The demo is just for showing the concept of setting the format on a specific block.
Plain text input
Format 1 (notice that it won't bother the current cursor in view)
Format 2
You can use QTextCursor to modify existing blocks.
Just get a cursor and move it to the beginning of the block. Then move it with anchor to create a selection.
Set this cursor to be the current cursor for the text edit and apply your changes.
QTextEdit accepts HTML so all you have to do is to format your paragraphs as HTML. See example below:
QString text = "<p><b>Paragraph 1</b></p><p><i>Paragraph 2</i></p>";
QTextCursor cursor = ui->textEdit->textCursor();
cursor.insertHtml(text);
That will create something like this:
Paragraph 1
Paragraph 2
Having said that, there is only a subset of HTML that is supported in Qt. See Supported HTML Subset

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.