src/declarative/util/qdeclarativefontloader.cpp
changeset 30 5dc02b23752f
child 33 3e2da88830cd
equal deleted inserted replaced
29:b72c6db6890b 30:5dc02b23752f
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "private/qdeclarativefontloader_p.h"
       
    43 
       
    44 #include <qdeclarativecontext.h>
       
    45 #include <qdeclarativeengine.h>
       
    46 
       
    47 #include <QStringList>
       
    48 #include <QUrl>
       
    49 #include <QDebug>
       
    50 #include <QNetworkRequest>
       
    51 #include <QNetworkReply>
       
    52 #include <QFile>
       
    53 #include <QFontDatabase>
       
    54 
       
    55 #include <private/qobject_p.h>
       
    56 #include <private/qdeclarativeengine_p.h>
       
    57 #include <qdeclarativeinfo.h>
       
    58 
       
    59 QT_BEGIN_NAMESPACE
       
    60 
       
    61 class QDeclarativeFontLoaderPrivate : public QObjectPrivate
       
    62 {
       
    63     Q_DECLARE_PUBLIC(QDeclarativeFontLoader)
       
    64 
       
    65 public:
       
    66     QDeclarativeFontLoaderPrivate() : reply(0), status(QDeclarativeFontLoader::Null), redirectCount(0) {}
       
    67 
       
    68     void addFontToDatabase(const QByteArray &);
       
    69 
       
    70     QUrl url;
       
    71     QString name;
       
    72     QNetworkReply *reply;
       
    73     QDeclarativeFontLoader::Status status;
       
    74     int redirectCount;
       
    75 };
       
    76 
       
    77 
       
    78 
       
    79 /*!
       
    80     \qmlclass FontLoader QDeclarativeFontLoader
       
    81     \since 4.7
       
    82     \brief This item allows using fonts by name or url.
       
    83 
       
    84     Example:
       
    85     \qml
       
    86     FontLoader { id: fixedFont; name: "Courier" }
       
    87     FontLoader { id: webFont; source: "http://www.mysite.com/myfont.ttf" }
       
    88 
       
    89     Text { text: "Fixed-size font"; font.family: fixedFont.name }
       
    90     Text { text: "Fancy font"; font.family: webFont.name }
       
    91     \endqml
       
    92 */
       
    93 QDeclarativeFontLoader::QDeclarativeFontLoader(QObject *parent)
       
    94     : QObject(*(new QDeclarativeFontLoaderPrivate), parent)
       
    95 {
       
    96 }
       
    97 
       
    98 QDeclarativeFontLoader::~QDeclarativeFontLoader()
       
    99 {
       
   100 }
       
   101 
       
   102 /*!
       
   103     \qmlproperty url FontLoader::source
       
   104     The url of the font to load.
       
   105 */
       
   106 QUrl QDeclarativeFontLoader::source() const
       
   107 {
       
   108     Q_D(const QDeclarativeFontLoader);
       
   109     return d->url;
       
   110 }
       
   111 
       
   112 void QDeclarativeFontLoader::setSource(const QUrl &url)
       
   113 {
       
   114     Q_D(QDeclarativeFontLoader);
       
   115     if (url == d->url)
       
   116         return;
       
   117     d->url = qmlContext(this)->resolvedUrl(url);
       
   118 
       
   119     d->status = Loading;
       
   120     emit statusChanged();
       
   121 #ifndef QT_NO_LOCALFILE_OPTIMIZED_QML
       
   122     QString lf = QDeclarativeEnginePrivate::urlToLocalFileOrQrc(d->url);
       
   123     if (!lf.isEmpty()) {
       
   124         int id = QFontDatabase::addApplicationFont(lf);
       
   125         if (id != -1) {
       
   126             d->name = QFontDatabase::applicationFontFamilies(id).at(0);
       
   127             emit nameChanged();
       
   128             d->status = QDeclarativeFontLoader::Ready;
       
   129         } else {
       
   130             d->status = QDeclarativeFontLoader::Error;
       
   131             qmlInfo(this) << "Cannot load font: \"" << url.toString() << "\"";
       
   132         }
       
   133         emit statusChanged();
       
   134     } else
       
   135 #endif
       
   136     {
       
   137         QNetworkRequest req(d->url);
       
   138         req.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
       
   139         d->reply = qmlEngine(this)->networkAccessManager()->get(req);
       
   140         QObject::connect(d->reply, SIGNAL(finished()), this, SLOT(replyFinished()));
       
   141     }
       
   142 }
       
   143 
       
   144 /*!
       
   145     \qmlproperty string FontLoader::name
       
   146 
       
   147     This property holds the name of the font family.
       
   148     It is set automatically when a font is loaded using the \c url property.
       
   149 
       
   150     Use this to set the \c font.family property of a \c Text item.
       
   151 
       
   152     Example:
       
   153     \qml
       
   154     FontLoader { id: webFont; source: "http://www.mysite.com/myfont.ttf" }
       
   155     Text { text: "Fancy font"; font.family: webFont.name }
       
   156     \endqml
       
   157 */
       
   158 QString QDeclarativeFontLoader::name() const
       
   159 {
       
   160     Q_D(const QDeclarativeFontLoader);
       
   161     return d->name;
       
   162 }
       
   163 
       
   164 void QDeclarativeFontLoader::setName(const QString &name)
       
   165 {
       
   166     Q_D(QDeclarativeFontLoader);
       
   167     if (d->name == name )
       
   168         return;
       
   169     d->name = name;
       
   170     emit nameChanged();
       
   171     d->status = Ready;
       
   172     emit statusChanged();
       
   173 }
       
   174 
       
   175 /*!
       
   176     \qmlproperty enumeration FontLoader::status
       
   177 
       
   178     This property holds the status of font loading.  It can be one of:
       
   179     \list
       
   180     \o FontLoader.Null - no font has been set
       
   181     \o FontLoader.Ready - the font has been loaded
       
   182     \o FontLoader.Loading - the font is currently being loaded
       
   183     \o FontLoader.Error - an error occurred while loading the font
       
   184     \endlist
       
   185 
       
   186     Note that a change in the status property does not cause anything to happen
       
   187     (although it reflects what has happened to the font loader internally). If you wish
       
   188     to react to the change in status you need to do it yourself, for example in one
       
   189     of the following ways:
       
   190     \list
       
   191     \o Create a state, so that a state change occurs, e.g. State{name: 'loaded'; when: loader.status = FontLoader.Ready;}
       
   192     \o Do something inside the onStatusChanged signal handler, e.g. FontLoader{id: loader; onStatusChanged: if(loader.status == FontLoader.Ready) console.log('Loaded');}
       
   193     \o Bind to the status variable somewhere, e.g. Text{text: if(loader.status!=FontLoader.Ready){'Not Loaded';}else{'Loaded';}}
       
   194     \endlist
       
   195 */
       
   196 QDeclarativeFontLoader::Status QDeclarativeFontLoader::status() const
       
   197 {
       
   198     Q_D(const QDeclarativeFontLoader);
       
   199     return d->status;
       
   200 }
       
   201 
       
   202 #define FONTLOADER_MAXIMUM_REDIRECT_RECURSION 16
       
   203 
       
   204 void QDeclarativeFontLoader::replyFinished()
       
   205 {
       
   206     Q_D(QDeclarativeFontLoader);
       
   207     if (d->reply) {
       
   208         d->redirectCount++;
       
   209         if (d->redirectCount < FONTLOADER_MAXIMUM_REDIRECT_RECURSION) {
       
   210             QVariant redirect = d->reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
       
   211             if (redirect.isValid()) {
       
   212                 QUrl url = d->reply->url().resolved(redirect.toUrl());
       
   213                 d->reply->deleteLater();
       
   214                 d->reply = 0;
       
   215                 setSource(url);
       
   216                 return;
       
   217             }
       
   218         }
       
   219         d->redirectCount=0;
       
   220 
       
   221         if (!d->reply->error()) {
       
   222             QByteArray ba = d->reply->readAll();
       
   223             d->addFontToDatabase(ba);
       
   224         } else {
       
   225             d->status = Error;
       
   226             qmlInfo(this) << "Cannot load font: \"" << d->reply->url().toString() << "\"";
       
   227             emit statusChanged();
       
   228         }
       
   229         d->reply->deleteLater();
       
   230         d->reply = 0;
       
   231     }
       
   232 }
       
   233 
       
   234 void QDeclarativeFontLoaderPrivate::addFontToDatabase(const QByteArray &ba)
       
   235 {
       
   236     Q_Q(QDeclarativeFontLoader);
       
   237 
       
   238     int id = QFontDatabase::addApplicationFontFromData(ba);
       
   239     if (id != -1) {
       
   240         name = QFontDatabase::applicationFontFamilies(id).at(0);
       
   241         emit q->nameChanged();
       
   242         status = QDeclarativeFontLoader::Ready;
       
   243     } else {
       
   244         status = QDeclarativeFontLoader::Error;
       
   245         qmlInfo(q) << "Cannot load font: \"" << url.toString() << "\"";
       
   246     }
       
   247     emit q->statusChanged();
       
   248 }
       
   249 
       
   250 QT_END_NAMESPACE