[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