1 /*
2     Copyright (C) 2008 Nokia Corporation and/or its subsidiary(-ies)
3 
4     This library is free software; you can redistribute it and/or
5     modify it under the terms of the GNU Library General Public
6     License as published by the Free Software Foundation; either
7     version 2 of the License, or (at your option) any later version.
8 
9     This library is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12     Library General Public License for more details.
13 
14     You should have received a copy of the GNU Library General Public License
15     along with this library; see the file COPYING.LIB.  If not, write to
16     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17     Boston, MA 02110-1301, USA.
18 
19     This class provides all functionality needed for loading images, style sheets and html
20     pages from the web. It has a memory cache for these objects.
21 */
22 #include "config.h"
23 #include "FontCustomPlatformData.h"
24 
25 #include "FontPlatformData.h"
26 #include "SharedBuffer.h"
27 #include "WOFFFileFormat.h"
28 #include <QFontDatabase>
29 #include <QMap>
30 #include <QStringList>
31 
32 namespace WebCore {
33 
~FontCustomPlatformData()34 FontCustomPlatformData::~FontCustomPlatformData()
35 {
36     QFontDatabase::removeApplicationFont(m_handle);
37 }
38 
fontPlatformData(int size,bool syntheticBold,bool syntheticItalic,FontOrientation,TextOrientation,FontWidthVariant,FontRenderingMode)39 FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool syntheticBold, bool syntheticItalic, FontOrientation, TextOrientation, FontWidthVariant, FontRenderingMode)
40 {
41     // Note that syntheticBold and syntheticItalic are only set by CSSFontSelector
42     // (the sole user of this class) if the markup has requested bold or italic
43     // (e.g. <i>text</i>) but the @font-face rule for the font does not specify support
44     // for it (e.g. @font-face { font-family: "font"; font-style: normal;).
45 
46     QFont font;
47     QFontDatabase db;
48 
49     QString family = QFontDatabase::applicationFontFamilies(m_handle)[0];
50     font.setFamily(family);
51     font.setPixelSize(size);
52     if (m_bold || syntheticBold)
53         font.setWeight(QFont::Bold);
54     font.setItalic(m_italic || syntheticItalic);
55 
56     return FontPlatformData(font);
57 }
58 
currentStyles(const QStringList & families,const QFontDatabase & db)59 static QMap<QString, QStringList> currentStyles(const QStringList& families, const QFontDatabase& db)
60 {
61     QMap<QString, QStringList> styles;
62     for (int i = 0; i < families.size(); ++i)
63         styles[families.at(i)].append(db.styles(families.at(i)));
64     return styles;
65 }
66 
stylesAddedByFont(const QString & familyAdded,const QStringList & stylesAdded,const QMap<QString,QStringList> & styles)67 static QStringList stylesAddedByFont(const QString& familyAdded, const QStringList& stylesAdded, const QMap<QString, QStringList>& styles)
68 {
69     QStringList newStyles = stylesAdded;
70     for (int i = 0; i < styles[familyAdded].size(); ++i)
71         newStyles.removeAll(styles[familyAdded].at(i));
72     return newStyles;
73 }
74 
strictlyItalicAddedByFont(const QString & familyAdded,const QStringList & stylesAdded,const QFontDatabase & db)75 static bool strictlyItalicAddedByFont(const QString& familyAdded, const QStringList& stylesAdded, const QFontDatabase& db)
76 {
77     bool italic = false;
78     for (int i = 0; i < stylesAdded.size(); ++i) {
79         if (db.italic(familyAdded, stylesAdded.at(i))) {
80             italic = true;
81         } else if (!db.bold(familyAdded, stylesAdded.at(i)))
82             return false;
83     }
84     return italic;
85 }
86 
strictlyBoldAddedByFont(const QString & familyAdded,const QStringList & stylesAdded,const QFontDatabase & db)87 static bool strictlyBoldAddedByFont(const QString& familyAdded, const QStringList& stylesAdded, const QFontDatabase& db)
88 {
89     bool bold = false;
90     for (int i = 0; i < stylesAdded.size(); ++i) {
91         if (db.bold(familyAdded, stylesAdded.at(i))) {
92             bold = true;
93         } else if (!db.italic(familyAdded, stylesAdded.at(i)))
94             return false;
95     }
96     return bold;
97 }
98 
createFontCustomPlatformData(SharedBuffer * buffer)99 FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
100 {
101     ASSERT_ARG(buffer, buffer);
102     QFontDatabase db;
103 
104     // The font families in the font database, and the styles in each,
105     // before we load the new font in buffer.
106     QStringList families = db.families();
107     QMap<QString, QStringList> styles = currentStyles(families, db);
108 
109     RefPtr<SharedBuffer> sfntBuffer;
110     if (isWOFF(buffer)) {
111         Vector<char> sfnt;
112         if (!convertWOFFToSfnt(buffer, sfnt))
113             return 0;
114         sfntBuffer = SharedBuffer::adoptVector(sfnt);
115         buffer = sfntBuffer.get();
116     }
117 
118     int id = QFontDatabase::addApplicationFontFromData(QByteArray(buffer->data(), buffer->size()));
119     if (id == -1)
120         return 0;
121 
122     QString familyAdded = QFontDatabase::applicationFontFamilies(id)[0];
123     QStringList stylesAdded = db.styles(QFontDatabase::applicationFontFamilies(id)[0]);
124 
125     // If we already had the family of which this font is a member then
126     // get the styles it added to the family
127     if (families.contains(familyAdded))
128         stylesAdded = stylesAddedByFont(familyAdded, stylesAdded, styles);
129 
130     Q_ASSERT(QFontDatabase::applicationFontFamilies(id).size() > 0);
131 
132     FontCustomPlatformData *data = new FontCustomPlatformData;
133     data->m_handle = id;
134 
135     // If we have created a font that only has bold or italic styles (or both)
136     // then we need to respect it's style(s) when we pass it back as
137     // FontPlatformData above.
138     data->m_italic = strictlyItalicAddedByFont(familyAdded, stylesAdded, db);
139     data->m_bold = strictlyBoldAddedByFont(familyAdded, stylesAdded, db);
140     return data;
141 }
142 
supportsFormat(const String & format)143 bool FontCustomPlatformData::supportsFormat(const String& format)
144 {
145     return equalIgnoringCase(format, "truetype") || equalIgnoringCase(format, "opentype") || equalIgnoringCase(format, "woff");
146 }
147 
148 }
149