diff options
author | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-31 21:27:18 +0000 |
---|---|---|
committer | agl@chromium.org <agl@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-10-31 21:27:18 +0000 |
commit | 6b1731c04c7855f0b03e0b52279f6ad114746158 (patch) | |
tree | 98032cf905ea77c9730c258a0f1df30ab2a0598f /webkit/port | |
parent | f095abfa66d4ec79d71079e3d89fd192fafaf82f (diff) | |
download | chromium_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')
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 |