[Qt-interest] External font loading in Qt Webkit
Strahinja Markovic
strahinja.markovic at gmail.com
Sun Jul 19 18:13:18 CEST 2009
Dear newsgroup,
I believe I have found a bug in Qt. It pertains to external font loading
with the “@font-face” CSS property.
Two issues are present:
1. If we load both the regular and the italic versions of a font face from
different font files and then specify that an HTML element should use that
font face, the regular version of the font is displayed, but not the italic.
Example CSS code:
@font-face { font-family: "Fontin"; src: url(Fontin-Regular.ttf); }
@font-face { font-family: "Fontin"; font-style: italic; src:
url(Fontin-Italic.ttf); }
body { font-family: "Fontin" }
The regular style is displayed correctly, the italic isn’t. Same thing
happens for bold versions and different font families/font files. Needless
to say, this works in Firefox 3.5 and Safari 4.0.2.
2. My application uses the “contentEditable” property to enable editing of
the loaded HTML file. If the user tries to make some regular text italic
with “CTRL + I” (or invokes the command in some other way), the text isn’t
displayed italic (because of issue #1, naturally). But if he then closes the
application, it crashes with a segfault.
I have also tried loading the fonts by hand with
“QFontDatabase::addApplicationFont(const QString & fileName)” and it made no
difference for either issue.
I am providing a small test application that demonstrates issue #1. But for
reasons that are beyond my comprehension, I am unable to replicate issue #2
in a test application, although it is very easy to replicate in my program.
Make sure that the font files are in the same folder as your executable, and
that they are not installed in the system.
I do have the next best thing for issue #2: start the “Browser” demo
application that comes with Qt and open the “test.xhtml” file that comes
with my test app for issue #1. Even without setting “contentEditable” to
true and making some text italic by hand, it will crash on exit with a
segfault. It will also display issue #1, that is, it won’t display italic
text as italic. I have analyzed the stack trace for the crash in the
“Browser” application and in my own, and they are practically identical: it’s
the same bug, although it’s invoked in slightly different ways. I have
included the stack trace for my application for reference.
I have zipped up the font files and the source files for the test
application and I have made it available at this location:
http://www.sendspace.com/file/rqkh07
For convenience, convention and posterity, the source files are inlined in
this email, and the font files used in the example can be downloaded
separately from here: http://www.josbuivenga.demon.nl/fontin.html
This has all been tested on Vista x64 and Ubuntu 9.04. The Qt versions used
were 4.5.2 and 4.5.0, respectively.
Sincerely,
Strahinja Markovic
************ test.xhtml ***************
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<style type="text/css">
@font-face { font-family: "Fontin"; src: url(Fontin-Regular.ttf); }
@font-face { font-family: "Fontin"; font-style: italic; src:
url(Fontin-Italic.ttf); }
body { font-family: "Fontin" }
</style>
</head>
<body>
<p>Normal text.</p>
<p><i>Italic text.</i></p>
</body>
</html>
********** fontsbug.pro ***************
QT += webkit
CONFIG += qt debug_and_release
HEADERS += mainwindow.h
SOURCES += main.cpp \
mainwindow.cpp
********** main.cpp *******************
#include <QApplication>
#include "mainwindow.h"
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
MainWindow mainWin;
mainWin.show();
return app.exec();
}
********** mainwindow.cpp *************
#include <QtGui>
#include <QtWebKit/QWebView>
#include "mainwindow.h"
MainWindow::MainWindow()
{
wvBrowser = new QWebView( this );
setCentralWidget( wvBrowser );
QString fullpath = QFileInfo( "test.xhtml" ).absoluteFilePath();
QFile file( fullpath );
if ( !file.open( QFile::ReadOnly | QFile::Text ) )
{
QMessageBox::warning( 0,
QObject::tr( "fontsbug" ),
QObject::tr( "Cannot read file %1:\n%2." )
.arg( fullpath )
.arg( file.errorString() )
);
return;
}
QTextStream in( &file );
QString html_source = in.readAll();
wvBrowser->setHtml( html_source, QUrl::fromLocalFile(
QCoreApplication::applicationDirPath() + "/" ) );
//wvBrowser->page()->setContentEditable( true );
}
********** mainwindow.h *************
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
class QWebView;
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
MainWindow();
private:
QWebView *wvBrowser;
};
#endif
*********** stacktrace for issue #2 *********
> QtCored4.dll!QObject::d_func() Line 118 + 0xa bytes C++
QtCored4.dll!QMetaObject::activate(QObject * sender=0x00000000, const
QMetaObject * m=0x65b2b130, int local_signal_index=2, void * *
argv=0x00000000) Line 3174 + 0x8 bytes C++
QtGuid4.dll!QApplication::fontDatabaseChanged() Line 179 + 0x13 bytes
C++
QtGuid4.dll!QFontDatabasePrivate::invalidate() Line 631 C++
QtGuid4.dll!QFontDatabase::removeApplicationFont(int handle=0) Line
1275 C++
QtWebKitd4.dll!WebCore::FontCustomPlatformData::~FontCustomPlatformData()
Line 34 + 0xc bytes C++
QtWebKitd4.dll!WebCore::FontCustomPlatformData::`scalar deleting
destructor'() + 0xf bytes C++
QtWebKitd4.dll!WebCore::CachedFont::allClientsRemoved() Line 179 + 0x22
bytes C++
QtWebKitd4.dll!WebCore::CachedResource::removeClient(WebCore::CachedResourceClient
* c=0x03b82bf0) Line 167 C++
QtWebKitd4.dll!WebCore::CSSFontFaceSource::~CSSFontFaceSource() Line 64
C++
QtWebKitd4.dll!WebCore::CSSFontFaceSource::`scalar deleting
destructor'() + 0xf bytes C++
QtWebKitd4.dll!WTF::deleteAllValues<WebCore::CSSFontFaceSource
*,0>(const WTF::Vector<WebCore::CSSFontFaceSource *,0> & collection={...})
Line 931 + 0x22 bytes C++
QtWebKitd4.dll!WebCore::CSSFontFace::~CSSFontFace() Line 39 + 0xc bytes
C++
QtWebKitd4.dll!WebCore::CSSFontFace::`scalar deleting destructor'() +
0xf bytes C++
QtWebKitd4.dll!WTF::RefCounted<WebCore::CSSFontFace>::deref() Line 96 +
0x1c bytes C++
QtWebKitd4.dll!WTF::RefPtr<WebCore::CSSFontFace>::~RefPtr<WebCore::CSSFontFace>()
Line 50 + 0x1f bytes C++
QtWebKitd4.dll!WTF::RefPtr<WebCore::CSSFontFace>::`scalar deleting
destructor'() + 0xf bytes C++
QtWebKitd4.dll!WTF::VectorDestructor<1,WTF::RefPtr<WebCore::CSSFontFace>
>::destruct(WTF::RefPtr<WebCore::CSSFontFace> * begin=0x03bf3a40,
WTF::RefPtr<WebCore::CSSFontFace> * end=0x03bf3a48) Line 80 + 0xa bytes C++
QtWebKitd4.dll!WTF::VectorTypeOperations<WTF::RefPtr<WebCore::CSSFontFace>
>::destruct(WTF::RefPtr<WebCore::CSSFontFace> * begin=0x03bf3a40,
WTF::RefPtr<WebCore::CSSFontFace> * end=0x03bf3a48) Line 235 + 0xd bytes
C++
QtWebKitd4.dll!WTF::Vector<WTF::RefPtr<WebCore::CSSFontFace>,0>::shrink(unsigned
int size=0) Line 708 + 0x1d bytes C++
QtWebKitd4.dll!WTF::Vector<WTF::RefPtr<WebCore::CSSFontFace>,0>::~Vector<WTF::RefPtr<WebCore::CSSFontFace>,0>()
Line 458 C++
QtWebKitd4.dll!WTF::Vector<WTF::RefPtr<WebCore::CSSFontFace>,0>::`scalar
deleting destructor'() + 0xf bytes C++
QtWebKitd4.dll!WTF::deleteAllPairSeconds<WTF::Vector<WTF::RefPtr<WebCore::CSSFontFace>,0>
*,WTF::HashMap<WebCore::String,WTF::Vector<WTF::RefPtr<WebCore::CSSFontFace>,0>
*,WebCore::CaseFoldingHash,WTF::HashTraits<WebCore::String>,WTF::HashTraits<WTF::Vector<WTF::RefPtr<WebCore::CSSFontFace>,0>
*> > const >(const
WTF::HashMap<WebCore::String,WTF::Vector<WTF::RefPtr<WebCore::CSSFontFace>,0>
*,WebCore::CaseFoldingHash,WTF::HashTraits<WebCore::String>,WTF::HashTraits<WTF::Vector<WTF::RefPtr<WebCore::CSSFontFace>,0>
*> > & collection={...}) Line 278 + 0x24 bytes C++
QtWebKitd4.dll!WTF::deleteAllValues<WebCore::String,WTF::Vector<WTF::RefPtr<WebCore::CSSFontFace>,0>
*,WebCore::CaseFoldingHash,WTF::HashTraits<WebCore::String>,WTF::HashTraits<WTF::Vector<WTF::RefPtr<WebCore::CSSFontFace>,0>
*> >(const
WTF::HashMap<WebCore::String,WTF::Vector<WTF::RefPtr<WebCore::CSSFontFace>,0>
*,WebCore::CaseFoldingHash,WTF::HashTraits<WebCore::String>,WTF::HashTraits<WTF::Vector<WTF::RefPtr<WebCore::CSSFontFace>,0>
*> > & collection={...}) Line 284 + 0x9 bytes C++
QtWebKitd4.dll!WebCore::CSSFontSelector::~CSSFontSelector() Line 74 +
0xc bytes C++
QtWebKitd4.dll!WebCore::CSSFontSelector::`scalar deleting destructor'()
+ 0xf bytes C++
QtWebKitd4.dll!WTF::RefCounted<WebCore::FontSelector>::deref() Line 96
+ 0x38 bytes C++
QtWebKitd4.dll!WTF::RefPtr<WebCore::FontSelector>::~RefPtr<WebCore::FontSelector>()
Line 50 + 0x22 bytes C++
QtWebKitd4.dll!WebCore::FontFallbackList::~FontFallbackList() Line 46 +
0x44 bytes C++
QtWebKitd4.dll!WebCore::FontFallbackList::`scalar deleting destructor'()
+ 0xf bytes C++
QtWebKitd4.dll!WTF::RefCounted<WebCore::FontFallbackList>::deref() Line
96 + 0x1c bytes C++
QtWebKitd4.dll!WTF::RefPtr<WebCore::FontFallbackList>::~RefPtr<WebCore::FontFallbackList>()
Line 50 + 0x1f bytes C++
QtWebKitd4.dll!WebCore::Font::~Font() Line 117 + 0x1a bytes C++
QtWebKitd4.dll!WebCore::StyleInheritedData::~StyleInheritedData() Line
46 + 0xb bytes C++
QtWebKitd4.dll!WebCore::StyleInheritedData::`scalar deleting
destructor'() + 0xf bytes C++
QtWebKitd4.dll!WTF::RefCounted<WebCore::StyleInheritedData>::deref()
Line 96 + 0x1c bytes C++
QtWebKitd4.dll!WTF::RefPtr<WebCore::StyleInheritedData>::~RefPtr<WebCore::StyleInheritedData>()
Line 50 + 0x1f bytes C++
QtWebKitd4.dll!WebCore::DataRef<WebCore::StyleInheritedData>::~DataRef<WebCore::StyleInheritedData>()
+ 0xf bytes C++
QtWebKitd4.dll!WebCore::RenderStyle::~RenderStyle() Line 165 + 0x29
bytes C++
QtWebKitd4.dll!WebCore::RenderStyle::`scalar deleting destructor'() +
0xf bytes C++
QtWebKitd4.dll!WTF::RefCounted<WebCore::RenderStyle>::deref() Line 96 +
0x1c bytes C++
QtWebKitd4.dll!WTF::RefPtr<WebCore::RenderStyle>::~RefPtr<WebCore::RenderStyle>()
Line 50 + 0x1f bytes C++
QtWebKitd4.dll!WebCore::CSSStyleSelector::~CSSStyleSelector() Line 484
+ 0xa2 bytes C++
QtWebKitd4.dll!WebCore::CSSStyleSelector::`scalar deleting destructor'()
+ 0xf bytes C++
QtWebKitd4.dll!WebCore::Document::~Document() Line 437 + 0x1f bytes C++
QtWebKitd4.dll!WebCore::HTMLDocument::~HTMLDocument() Line 91 + 0x41
bytes C++
QtWebKitd4.dll!WebCore::HTMLDocument::`scalar deleting destructor'() +
0xf bytes C++
QtWebKitd4.dll!WebCore::Document::selfOnlyDeref() Line 207 + 0x20 bytes
C++
QtWebKitd4.dll!WebCore::DocPtr<WebCore::Document>::~DocPtr<WebCore::Document>()
Line 32 + 0x1f bytes C++
QtWebKitd4.dll!WebCore::Document::removedLastRef() Line 414 + 0xf bytes
C++
QtWebKitd4.dll!WebCore::TreeShared<WebCore::Node>::deref() Line 71 C++
QtWebKitd4.dll!WTF::RefPtr<WebCore::Node>::~RefPtr<WebCore::Node>()
Line 50 + 0x1f bytes C++
QtWebKitd4.dll!WebCore::JSNode::~JSNode() Line 207 + 0xf bytes C++
QtWebKitd4.dll!WebCore::JSEventTargetNode::~JSEventTargetNode() + 0xf
bytes C++
QtWebKitd4.dll!WebCore::JSDocument::~JSDocument() Line 251 + 0xf bytes
C++
QtWebKitd4.dll!WebCore::JSHTMLDocument::~JSHTMLDocument() + 0xf bytes
C++
QtWebKitd4.dll!WebCore::JSHTMLDocument::`scalar deleting destructor'()
+ 0xf bytes C++
QtWebKitd4.dll!JSC::Heap::sweep<0>() Line 1024 C++
QtWebKitd4.dll!JSC::Heap::collect() Line 1099 + 0x8 bytes C++
QtWebKitd4.dll!WebCore::GCController::gcTimerFired(WebCore::Timer<WebCore::GCController>
* __formal=0x03afc218) Line 75 C++
QtWebKitd4.dll!WebCore::Timer<WebCore::GCController>::fired() Line 99 +
0x19 bytes C++
QtWebKitd4.dll!WebCore::TimerBase::fireTimers(double
fireTime=1248014279.8780918, const WTF::Vector<WebCore::TimerBase *,0> &
firingTimers={...}) Line 350 C++
QtWebKitd4.dll!WebCore::TimerBase::sharedTimerFired() Line 368 + 0x12
bytes C++
QtWebKitd4.dll!WebCore::SharedTimerQt::~SharedTimerQt() Line 69 C++
QtWebKitd4.dll!WebCore::SharedTimerQt::`scalar deleting destructor'() +
0xf bytes C++
QtCored4.dll!QObjectPrivate::deleteChildren() Line 1838 + 0x24 bytes
C++
QtCored4.dll!QObject::~QObject() Line 838 C++
QtCored4.dll!QCoreApplication::~QCoreApplication() Line 537 + 0xf bytes
C++
QtGuid4.dll!QApplication::~QApplication() Line 1075 + 0x13 bytes C++
Sigil.exe!main(int argc=1, char * * argv=0x01728690) Line 40 + 0x2b
bytes C++
Sigil.exe!WinMain(HINSTANCE__ * instance=0x01100000, HINSTANCE__ *
prevInstance=0x00000000, char * __formal=0x00716c3e, int cmdShow=1) Line
136 + 0x12 bytes C++
Sigil.exe!__tmainCRTStartup() Line 578 + 0x35 bytes C
Sigil.exe!WinMainCRTStartup() Line 403 C
kernel32.dll!750feccb()
[Frames below may be incorrect and/or missing, no symbols loaded for
kernel32.dll]
ntdll.dll!76fcd24d()
ntdll.dll!76fcd45f()
More information about the Qt-interest-old
mailing list