summaryrefslogtreecommitdiffstats
path: root/webkit/port
diff options
context:
space:
mode:
authoragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-31 21:27:18 +0000
committeragl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-31 21:27:18 +0000
commit6b1731c04c7855f0b03e0b52279f6ad114746158 (patch)
tree98032cf905ea77c9730c258a0f1df30ab2a0598f /webkit/port
parentf095abfa66d4ec79d71079e3d89fd192fafaf82f (diff)
downloadchromium_src-6b1731c04c7855f0b03e0b52279f6ad114746158.zip
chromium_src-6b1731c04c7855f0b03e0b52279f6ad114746158.tar.gz
chromium_src-6b1731c04c7855f0b03e0b52279f6ad114746158.tar.bz2
Get fonts to render in a somewhat recognisable form on Linux.
Review URL: http://codereview.chromium.org/8936 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@4325 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/port')
-rw-r--r--webkit/port/platform/graphics/chromium/FontCacheLinux.cpp22
-rw-r--r--webkit/port/platform/graphics/chromium/FontLinux.cpp56
-rw-r--r--webkit/port/platform/graphics/chromium/FontPlatformDataLinux.cpp136
-rw-r--r--webkit/port/platform/graphics/chromium/FontPlatformDataLinux.h52
-rw-r--r--webkit/port/platform/graphics/chromium/GlyphPageTreeNodeLinux.cpp35
-rw-r--r--webkit/port/platform/graphics/chromium/SimpleFontDataLinux.cpp67
6 files changed, 309 insertions, 59 deletions
diff --git a/webkit/port/platform/graphics/chromium/FontCacheLinux.cpp b/webkit/port/platform/graphics/chromium/FontCacheLinux.cpp
index 6630f670..2163c45 100644
--- a/webkit/port/platform/graphics/chromium/FontCacheLinux.cpp
+++ b/webkit/port/platform/graphics/chromium/FontCacheLinux.cpp
@@ -4,16 +4,20 @@
#include "config.h"
#include "FontCache.h"
-#include "AtomicString.h"
+#include "AtomicString.h"
+#include "FontDescription.h"
+#include "FontPlatformData.h"
+#include "Logging.h"
#include "NotImplemented.h"
namespace WebCore {
-// TODO(agl): stubs only
-
-
-void FontCache::platformInit() { }
+void FontCache::platformInit()
+{
+ if (!FontPlatformData::init())
+ ASSERT_NOT_REACHED();
+}
const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font,
const UChar* characters,
@@ -35,13 +39,14 @@ const AtomicString& FontCache::alternateFamilyName(const AtomicString& familyNam
FontPlatformData* FontCache::getSimilarFontPlatformData(const Font& font)
{
+ notImplemented();
return 0;
}
FontPlatformData* FontCache::getLastResortFallbackFont(const FontDescription& description)
{
- notImplemented();
- return 0;
+ static AtomicString arialStr("Arial");
+ return getCachedFontPlatformData(description, arialStr);
}
void FontCache::getTraitsInFamily(const AtomicString& familyName,
@@ -53,8 +58,7 @@ void FontCache::getTraitsInFamily(const AtomicString& familyName,
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription,
const AtomicString& family)
{
- notImplemented();
- return 0;
+ return new FontPlatformData(fontDescription, family);
}
AtomicString FontCache::getGenericFontForScript(UScriptCode script,
diff --git a/webkit/port/platform/graphics/chromium/FontLinux.cpp b/webkit/port/platform/graphics/chromium/FontLinux.cpp
index 9ee965f..2c186d1 100644
--- a/webkit/port/platform/graphics/chromium/FontLinux.cpp
+++ b/webkit/port/platform/graphics/chromium/FontLinux.cpp
@@ -5,18 +5,64 @@
#include "config.h"
#include "Font.h"
+#include <pango/pango.h>
+#include <pango/pangoft2.h>
+
#include "FloatRect.h"
#include "NotImplemented.h"
+#include "PlatformContextSkia.h"
+#include "GraphicsContext.h"
+#include "SimpleFontData.h"
+#include "GlyphBuffer.h"
namespace WebCore {
-// TODO(agl): stubs only
+// -----------------------------------------------------------------------------
+// Bitblit a Freetype bitmap onto a canvas at the given location in the given
+// colour.
+// pgc: the Skia canvas
+// bm: A freetype bitmap which is an 8-bit alpha bitmap
+// -----------------------------------------------------------------------------
+static void bitBlitAlpha(PlatformGraphicsContext* pgc, FT_Bitmap* bm,
+ int x, int y, const Color& col)
+{
+ SkPaint paint;
+ paint.setARGB(col.alpha(), col.red(), col.green(), col.blue());
+
+ // Here we are constructing an SkBitmap by pointing directly into the
+ // Freetype bitmap data
+ SkBitmap glyph;
+ glyph.setConfig(SkBitmap::kA8_Config, bm->width, bm->rows, bm->pitch);
+ glyph.setPixels(bm->buffer);
+ pgc->canvas()->drawBitmap(glyph, x, y, &paint);
+}
-void Font::drawGlyphs(GraphicsContext*, const SimpleFontData*,
- const GlyphBuffer&, int from, int to,
- const FloatPoint&) const
+void Font::drawGlyphs(GraphicsContext* ctx, const SimpleFontData* sfd,
+ const GlyphBuffer& glyphBuffer, int from, int to,
+ const FloatPoint& point) const
{
- notImplemented();
+ // For now we draw text by getting the Freetype face from Pango and asking
+ // Freetype to render each glyph as an 8-bit alpha bitmap and drawing that
+ // to the canvas. This, obviously, ignores kerning, ligatures and other
+ // things that we should have in the real version.
+ GlyphBufferGlyph* glyphs = (GlyphBufferGlyph*)glyphBuffer.glyphs(from);
+ PlatformGraphicsContext* pgc = ctx->platformContext();
+ FT_Face face = pango_ft2_font_get_face(sfd->m_font.m_font);
+ FT_GlyphSlot slot = face->glyph;
+
+ int x = point.x(), y = point.y();
+
+ for (int i = from; i < to; ++i) {
+ const FT_Error error = FT_Load_Glyph(face, glyphs[i], FT_LOAD_RENDER);
+ if (error)
+ continue;
+
+ bitBlitAlpha(pgc, &slot->bitmap, x + slot->bitmap_left,
+ y - slot->bitmap_top, ctx->fillColor());
+ // Freetype works in 1/64ths of a pixel, so we divide by 64 to get the
+ // number of pixels to advance.
+ x += slot->advance.x >> 6;
+ }
}
void Font::drawComplexText(GraphicsContext* context, const TextRun& run,
diff --git a/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.cpp b/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.cpp
index 855d6d8..e14a023 100644
--- a/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.cpp
+++ b/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.cpp
@@ -5,51 +5,133 @@
#include "config.h"
#include "FontPlatformData.h"
+#include <gtk/gtk.h>
+#include <pango/pango.h>
+#include <pango/pangoft2.h>
+
+#include "CString.h"
+#include "FontDescription.h"
#include "NotImplemented.h"
+#include "PlatformString.h"
namespace WebCore {
-// TODO(agl): stubs only
+PangoFontMap* FontPlatformData::m_fontMap = 0;
+GHashTable* FontPlatformData::m_hashTable = 0;
-FontPlatformData::FontPlatformData() {
- notImplemented();
-}
+FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName)
+ : m_context(0)
+ , m_font(0)
+ , m_size(fontDescription.computedSize())
+ , m_syntheticBold(false)
+ , m_syntheticOblique(false)
+{
+ FontPlatformData::init();
-FontPlatformData::FontPlatformData(WTF::HashTableDeletedValueType) {
- notImplemented();
-}
+ CString stored_family = familyName.string().utf8();
+ char const* families[] = {
+ stored_family.data(),
+ NULL
+ };
-FontPlatformData::FontPlatformData(const FontDescription& fontDescription,
- const AtomicString& familyName) {
- notImplemented();
-}
+ switch (fontDescription.genericFamily()) {
+ case FontDescription::SerifFamily:
+ families[1] = "serif";
+ break;
+ case FontDescription::SansSerifFamily:
+ families[1] = "sans";
+ break;
+ case FontDescription::MonospaceFamily:
+ families[1] = "monospace";
+ break;
+ case FontDescription::NoFamily:
+ case FontDescription::StandardFamily:
+ default:
+ families[1] = "sans";
+ break;
+ }
+
+ PangoFontDescription* description = pango_font_description_new();
+ pango_font_description_set_absolute_size(description, fontDescription.computedSize() * PANGO_SCALE);
+
+ // FIXME: Map all FontWeight values to Pango font weights.
+ if (fontDescription.weight() >= FontWeight600)
+ pango_font_description_set_weight(description, PANGO_WEIGHT_BOLD);
+ if (fontDescription.italic())
+ pango_font_description_set_style(description, PANGO_STYLE_ITALIC);
+
+ m_context = pango_ft2_font_map_create_context(PANGO_FT2_FONT_MAP(m_fontMap));
+
+ for (unsigned int i = 0; !m_font && i < G_N_ELEMENTS(families); i++) {
+ pango_font_description_set_family(description, families[i]);
+ pango_context_set_font_description(m_context, description);
+ m_font = pango_font_map_load_font(m_fontMap, m_context, description);
+ }
-FontPlatformData::FontPlatformData(float size, bool bold, bool oblique) {
- notImplemented();
+ pango_font_description_free(description);
}
-FontPlatformData::~FontPlatformData() {
- notImplemented();
+FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
+ : m_context(0)
+ , m_font(0)
+ , m_size(size)
+ , m_syntheticBold(bold)
+ , m_syntheticOblique(oblique)
+{
}
-bool FontPlatformData::isHashTableDeletedValue() const {
- notImplemented();
- return false;
+bool FontPlatformData::init()
+{
+ static bool initialized = false;
+ if (initialized)
+ return true;
+ initialized = true;
+
+ if (!m_fontMap)
+ m_fontMap = pango_ft2_font_map_new();
+ if (!m_hashTable) {
+ PangoFontFamily** families = 0;
+ int n_families = 0;
+
+ m_hashTable = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref);
+
+ pango_font_map_list_families(m_fontMap, &families, &n_families);
+
+ for (int family = 0; family < n_families; family++)
+ g_hash_table_insert(m_hashTable,
+ g_strdup(pango_font_family_get_name(families[family])),
+ g_object_ref(families[family]));
+
+ g_free(families);
+ }
+
+ return true;
}
-unsigned FontPlatformData::hash() const {
- notImplemented();
- return 0;
+bool FontPlatformData::isFixedPitch() const
+{
+ PangoFontDescription* description = pango_font_describe_with_absolute_size(m_font);
+ PangoFontFamily* family = reinterpret_cast<PangoFontFamily*>(g_hash_table_lookup(m_hashTable, pango_font_description_get_family(description)));
+ pango_font_description_free(description);
+ return pango_font_family_is_monospace(family);
}
-bool FontPlatformData::operator==(const FontPlatformData &other) const {
- notImplemented();
- return false;
+FontPlatformData::~FontPlatformData() {
}
-float FontPlatformData::size() const {
- notImplemented();
- return 0;
+bool FontPlatformData::operator==(const FontPlatformData& other) const
+{
+ if (m_font == other.m_font)
+ return true;
+ if (m_font == 0 || m_font == reinterpret_cast<PangoFont*>(-1)
+ || other.m_font == 0 || other.m_font == reinterpret_cast<PangoFont*>(-1))
+ return false;
+ PangoFontDescription* thisDesc = pango_font_describe(m_font);
+ PangoFontDescription* otherDesc = pango_font_describe(other.m_font);
+ bool result = pango_font_description_equal(thisDesc, otherDesc);
+ pango_font_description_free(otherDesc);
+ pango_font_description_free(thisDesc);
+ return result;
}
} // namespace WebCore
diff --git a/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.h b/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.h
index 383fbf3..b8ae94f 100644
--- a/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.h
+++ b/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.h
@@ -8,7 +8,10 @@
#include "config.h"
#include "build/build_config.h"
+#include <pango/pango.h>
+
#include "StringImpl.h"
+#include "NotImplemented.h"
#include <wtf/PassRefPtr.h>
#include <wtf/RefCounted.h>
@@ -16,20 +19,55 @@ namespace WebCore {
class FontDescription;
-// TODO(agl): stubs only
-
class FontPlatformData {
public:
- FontPlatformData();
- FontPlatformData(WTF::HashTableDeletedValueType);
+ // Used for deleted values in the font cache's hash tables. The hash table
+ // will create us with this structure, and it will compare other values
+ // to this "Deleted" one. It expects the Deleted one to be differentiable
+ // from the NULL one (created with the empty constructor), so we can't just
+ // set everything to NULL.
+ FontPlatformData(WTF::HashTableDeletedValueType)
+ : m_context(0)
+ , m_font(hashTableDeletedFontValue())
+ { }
+
+ FontPlatformData()
+ : m_context(0)
+ , m_font(0)
+ { }
+
FontPlatformData(const FontDescription&, const AtomicString& family);
+
FontPlatformData(float size, bool bold, bool oblique);
+
~FontPlatformData();
- bool isHashTableDeletedValue() const;
- unsigned hash() const;
+ static bool init();
+
+ bool isFixedPitch() const;
+ float size() const { return m_size; }
+
+ unsigned hash() const
+ {
+ notImplemented();
+ return 0;
+ }
+
bool operator==(const FontPlatformData& other) const;
- float size() const;
+ bool isHashTableDeletedValue() const { return m_font == hashTableDeletedFontValue(); }
+
+ static PangoFontMap* m_fontMap;
+ static GHashTable* m_hashTable;
+
+ PangoContext* m_context;
+ PangoFont* m_font;
+
+ float m_size;
+ bool m_syntheticBold;
+ bool m_syntheticOblique;
+
+private:
+ static PangoFont* hashTableDeletedFontValue() { return reinterpret_cast<PangoFont*>(-1); }
};
} // namespace WebCore
diff --git a/webkit/port/platform/graphics/chromium/GlyphPageTreeNodeLinux.cpp b/webkit/port/platform/graphics/chromium/GlyphPageTreeNodeLinux.cpp
index 8dece07..1e7eb79 100644
--- a/webkit/port/platform/graphics/chromium/GlyphPageTreeNodeLinux.cpp
+++ b/webkit/port/platform/graphics/chromium/GlyphPageTreeNodeLinux.cpp
@@ -28,19 +28,46 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "config.h"
+#include "GlyphPageTreeNode.h"
+
+// This PANGO_ENABLE_BACKEND define lets us get at some of the internal Pango
+// call which we need. This include must be here otherwise we include pango.h
+// via another route (without the define) and that sets the include guard.
+// Then, when we try to include it in the future the guard stops us getting the
+// functions that we need.
+#define PANGO_ENABLE_BACKEND
+#include <pango/pango.h>
+#include <pango/pangofc-font.h>
#include "Font.h"
-#include "GlyphPageTreeNode.h"
#include "NotImplemented.h"
#include "SimpleFontData.h"
namespace WebCore
{
-bool GlyphPage::fill(unsigned offset, unsigned length, UChar* characterBuffer, unsigned bufferLength, const SimpleFontData* fontData)
+bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
- notImplemented();
- return false;
+ // The bufferLength will be greater than the glyph page size if the buffer has Unicode supplementary characters.
+ // We won't support this for now.
+ if (bufferLength > GlyphPage::size)
+ return false;
+
+ if (!fontData->m_font.m_font || fontData->m_font.m_font == reinterpret_cast<PangoFont*>(-1))
+ return false;
+
+ bool haveGlyphs = false;
+ for (unsigned i = 0; i < length; i++) {
+ Glyph glyph = pango_fc_font_get_glyph(PANGO_FC_FONT(fontData->m_font.m_font), buffer[i]);
+ if (!glyph)
+ setGlyphDataForIndex(offset + i, 0, 0);
+ else {
+ setGlyphDataForIndex(offset + i, glyph, fontData);
+ haveGlyphs = true;
+ }
+ }
+
+ return haveGlyphs;
}
} // namespace WebCore
diff --git a/webkit/port/platform/graphics/chromium/SimpleFontDataLinux.cpp b/webkit/port/platform/graphics/chromium/SimpleFontDataLinux.cpp
index 4525bd3..26caef8 100644
--- a/webkit/port/platform/graphics/chromium/SimpleFontDataLinux.cpp
+++ b/webkit/port/platform/graphics/chromium/SimpleFontDataLinux.cpp
@@ -2,19 +2,53 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#define PANGO_ENABLE_BACKEND
+
#include "config.h"
+#include "SimpleFontData.h"
+
+#include <pango/pango.h>
+#include <pango/pangoft2.h>
+#include <pango/pangofc-font.h>
+
#include "Font.h"
#include "FontCache.h"
-#include "SimpleFontData.h"
#include "FloatRect.h"
#include "FontDescription.h"
+#include "Logging.h"
#include "NotImplemented.h"
namespace WebCore {
// TODO(agl): only stubs
-void SimpleFontData::platformInit() { }
+void SimpleFontData::platformInit()
+{
+ PangoFont *const font = platformData().m_font;
+
+ PangoFontMetrics *const metrics = pango_font_get_metrics(font, NULL);
+ m_ascent = pango_font_metrics_get_ascent(metrics) / PANGO_SCALE;
+ m_descent = pango_font_metrics_get_descent(metrics) / PANGO_SCALE;
+ m_lineSpacing = m_ascent + m_descent;
+ m_avgCharWidth = pango_font_metrics_get_approximate_char_width(metrics) / PANGO_SCALE;
+ pango_font_metrics_unref(metrics);
+
+ const guint xglyph = pango_fc_font_get_glyph(PANGO_FC_FONT(font), 'x');
+ const guint spaceglyph = pango_fc_font_get_glyph(PANGO_FC_FONT(font), ' ');
+ PangoRectangle rect;
+
+ pango_font_get_glyph_extents(font, xglyph, &rect, NULL);
+ m_xHeight = rect.height / PANGO_SCALE;
+ pango_font_get_glyph_extents(font, spaceglyph, NULL, &rect);
+ m_spaceWidth = rect.width / PANGO_SCALE;
+ m_lineGap = m_lineSpacing - m_ascent - m_descent;
+
+ FT_Face face = pango_ft2_font_get_face(font);
+ m_unitsPerEm = face->units_per_EM / PANGO_SCALE;
+
+ // TODO(agl): I'm not sure we have good data for this so it's 0 for now
+ m_maxCharWidth = 0;
+}
void SimpleFontData::platformDestroy() { }
@@ -27,19 +61,38 @@ SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDes
bool SimpleFontData::containsCharacters(const UChar* characters,
int length) const
{
- notImplemented();
- return false;
+ bool result = true;
+
+ PangoCoverage* requested = pango_coverage_from_bytes((guchar*)characters, length);
+ PangoCoverage* available = pango_font_get_coverage(m_font.m_font, pango_language_get_default());
+ pango_coverage_max(requested, available);
+
+ for (int i = 0; i < length; i++) {
+ if (PANGO_COVERAGE_NONE == pango_coverage_get(requested, i)) {
+ result = false;
+ break;
+ }
+ }
+
+ pango_coverage_unref(requested);
+ pango_coverage_unref(available);
+
+ return result;
}
void SimpleFontData::determinePitch()
{
- notImplemented();
+ m_treatAsFixedPitch = platformData().isFixedPitch();
}
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
- notImplemented();
- return 0;
+ PangoFont *const font = platformData().m_font;
+ PangoRectangle rect;
+
+ pango_font_get_glyph_extents(font, glyph, NULL, &rect);
+
+ return static_cast<float>(rect.width) / PANGO_SCALE;
}
} // namespace WebCore