summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--skia/SConscript10
-rw-r--r--skia/ports/SkFontHost_FreeType.cpp8
-rw-r--r--skia/ports/SkFontHost_fontconfig.cpp323
-rw-r--r--webkit/port/platform/graphics/chromium/FontCacheLinux.cpp52
-rw-r--r--webkit/port/platform/graphics/chromium/FontLinux.cpp94
-rw-r--r--webkit/port/platform/graphics/chromium/FontPlatformDataLinux.cpp175
-rw-r--r--webkit/port/platform/graphics/chromium/FontPlatformDataLinux.h73
-rw-r--r--webkit/port/platform/graphics/chromium/GlyphPageTreeNodeLinux.cpp47
-rw-r--r--webkit/port/platform/graphics/chromium/SimpleFontDataLinux.cpp130
9 files changed, 638 insertions, 274 deletions
diff --git a/skia/SConscript b/skia/SConscript
index 283d371..8dfd26a 100644
--- a/skia/SConscript
+++ b/skia/SConscript
@@ -154,6 +154,16 @@ input_files = [
'sgl/SkXfermode.cpp',
]
+if env['PLATFORM'] == 'posix':
+ # On Linux we use Skia to render fonts with FreeType and fontconfig
+ input_files.remove('sgl/SkTypeface_fake.cpp')
+ input_files.remove('ports/SkFontHost_none.cpp')
+ input_files.append('sgl/SkTypeface.cpp')
+ input_files.append('ports/SkFontHost_FreeType.cpp')
+ input_files.append('ports/SkFontHost_gamma.cpp')
+ input_files.append('ports/SkFontHost_fontconfig.cpp')
+ input_files.append('images/SkMMapStream.cpp')
+
if env['PLATFORM'] in ('darwin', 'posix'):
input_files.append('ports/SkThread_pthread.cpp')
diff --git a/skia/ports/SkFontHost_FreeType.cpp b/skia/ports/SkFontHost_FreeType.cpp
index 4866f88..6430d2d 100644
--- a/skia/ports/SkFontHost_FreeType.cpp
+++ b/skia/ports/SkFontHost_FreeType.cpp
@@ -717,14 +717,6 @@ void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, SkPath* path)
path->close();
}
-static void map_y_to_pt(const FT_Matrix& mat, SkFixed y, SkPoint* pt)
-{
- SkFixed x = SkFixedMul(mat.xy, y);
- y = SkFixedMul(mat.yy, y);
-
- pt->set(SkFixedToScalar(x), SkFixedToScalar(y));
-}
-
void SkScalerContext_FreeType::generateFontMetrics(SkPaint::FontMetrics* mx, SkPaint::FontMetrics* my)
{
if (NULL == mx && NULL == my)
diff --git a/skia/ports/SkFontHost_fontconfig.cpp b/skia/ports/SkFontHost_fontconfig.cpp
new file mode 100644
index 0000000..2836db3
--- /dev/null
+++ b/skia/ports/SkFontHost_fontconfig.cpp
@@ -0,0 +1,323 @@
+/* libs/graphics/ports/SkFontHost_fontconfig.cpp
+**
+** Copyright 2008, Google Inc.
+**
+** Licensed under the Apache License, Version 2.0 (the "License");
+** you may not use this file except in compliance with the License.
+** You may obtain a copy of the License at
+**
+** http://www.apache.org/licenses/LICENSE-2.0
+**
+** Unless required by applicable law or agreed to in writing, software
+** distributed under the License is distributed on an "AS IS" BASIS,
+** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+** See the License for the specific language governing permissions and
+** limitations under the License.
+*/
+
+// -----------------------------------------------------------------------------
+// This file provides implementations of the font resolution members of
+// SkFontHost by using the fontconfig[1] library. Fontconfig is usually found
+// on Linux systems and handles configuration, parsing and caching issues
+// involved with enumerating and matching fonts.
+//
+// [1] http://fontconfig.org
+// -----------------------------------------------------------------------------
+
+#include <map>
+#include <string>
+
+#include <fontconfig/fontconfig.h>
+
+#include "SkDescriptor.h"
+#include "SkFontHost.h"
+#include "SkMMapStream.h"
+#include "SkPaint.h"
+#include "SkStream.h"
+#include "SkString.h"
+#include "SkThread.h"
+#include "SkTSearch.h"
+
+// This is an extern from SkFontHost_FreeType
+SkTypeface::Style find_name_and_style(SkStream* stream, SkString* name);
+
+// -----------------------------------------------------------------------------
+// The rest of Skia requires that fonts be identified by a unique unsigned id
+// and that we be able to load them given the id. What we actually get from
+// fontconfig is the filename of the font so we keep a locked map from
+// filenames to fileid numbers and back.
+//
+// Note that there's also a unique id in the SkTypeface. This is unique over
+// both filename and style. Thus we encode that id as (fileid << 8) | style.
+// Although truetype fonts can support multiple faces in a single file, at the
+// moment Skia doesn't.
+// -----------------------------------------------------------------------------
+static SkMutex global_fc_map_lock;
+static std::map<std::string, unsigned> global_fc_map;
+static std::map<unsigned, std::string> global_fc_map_inverted;
+static unsigned global_fc_map_next_id = 0;
+
+// This is the maximum size of the font cache.
+static const unsigned kFontCacheMemoryBudget = 2 * 1024 * 1024; // 2MB
+
+static unsigned UniqueIdToFileId(unsigned uniqueid)
+{
+ return uniqueid >> 8;
+}
+
+static SkTypeface::Style UniqueIdToStyle(unsigned uniqueid)
+{
+ return static_cast<SkTypeface::Style>(uniqueid & 0xff);
+}
+
+static unsigned FileIdAndStyleToUniqueId(unsigned fileid,
+ SkTypeface::Style style)
+{
+ SkASSERT(style & 0xff == style);
+ return (fileid << 8) | static_cast<int>(style);
+}
+
+class FontConfigTypeface : public SkTypeface {
+public:
+ FontConfigTypeface(Style style, uint32_t id)
+ : SkTypeface(style, id)
+ { }
+};
+
+// -----------------------------------------------------------------------------
+// Find a matching font where @type (one of FC_*) is equal to @value. For a
+// list of types, see http://fontconfig.org/fontconfig-devel/x19.html#AEN27.
+// The variable arguments are a list of triples, just like the first three
+// arguments, and must be NULL terminated.
+//
+// For example, FontMatchString(FC_FILE, FcTypeString,
+// "/usr/share/fonts/myfont.ttf", NULL);
+// -----------------------------------------------------------------------------
+static FcPattern* FontMatch(const char* type, FcType vtype, const void* value,
+ ...)
+{
+ va_list ap;
+ va_start(ap, value);
+
+ FcPattern* pattern = FcPatternCreate();
+
+ for (;;) {
+ FcValue fcvalue;
+ fcvalue.type = vtype;
+ switch (vtype) {
+ case FcTypeString:
+ fcvalue.u.s = (FcChar8*) value;
+ break;
+ case FcTypeInteger:
+ fcvalue.u.i = (int) value;
+ break;
+ default:
+ SkASSERT(!"FontMatch unhandled type");
+ }
+ FcPatternAdd(pattern, type, fcvalue, 0);
+
+ type = va_arg(ap, const char *);
+ if (!type)
+ break;
+ // FcType is promoted to int when passed through ...
+ vtype = static_cast<FcType>(va_arg(ap, int));
+ value = va_arg(ap, const void *);
+ };
+ va_end(ap);
+
+ FcConfigSubstitute(0, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+
+ FcResult result;
+ FcPattern* match = FcFontMatch(0, pattern, &result);
+ FcPatternDestroy(pattern);
+
+ return match;
+}
+
+// -----------------------------------------------------------------------------
+// Check to see if the filename has already been assigned a fileid and, if so,
+// use it. Otherwise, assign one. Return the resulting fileid.
+// -----------------------------------------------------------------------------
+static unsigned FileIdFromFilename(const char* filename)
+{
+ SkAutoMutexAcquire ac(global_fc_map_lock);
+
+ std::map<std::string, unsigned>::const_iterator i =
+ global_fc_map.find(filename);
+ if (i == global_fc_map.end()) {
+ const unsigned fileid = global_fc_map_next_id++;
+ global_fc_map[filename] = fileid;
+ global_fc_map_inverted[fileid] = filename;
+ return fileid;
+ } else {
+ return i->second;
+ }
+}
+
+SkTypeface* SkFontHost::FindTypeface(const SkTypeface* familyFace,
+ const char familyName[],
+ SkTypeface::Style style)
+{
+ const char* resolved_family_name = NULL;
+ FcPattern* face_match = NULL;
+
+ if (familyFace) {
+ // Here we use the inverted global id map to find the filename from the
+ // SkTypeface object. Given the filename we can ask fontconfig for the
+ // familyname of the font.
+ SkAutoMutexAcquire ac(global_fc_map_lock);
+
+ const unsigned fileid = UniqueIdToFileId(familyFace->uniqueID());
+ std::map<unsigned, std::string>::const_iterator i =
+ global_fc_map_inverted.find(fileid);
+ if (i == global_fc_map_inverted.end())
+ return NULL;
+
+ FcInit();
+ face_match = FontMatch(FC_FILE, FcTypeString, i->second.c_str(), NULL);
+
+ if (!face_match)
+ return NULL;
+ FcChar8* family;
+ if (FcPatternGetString(face_match, FC_FAMILY, 0, &family)) {
+ FcPatternDestroy(face_match);
+ return NULL;
+ }
+ // At this point, @family is pointing into the @face_match object so we
+ // cannot release it yet.
+
+ resolved_family_name = reinterpret_cast<char*>(family);
+ } else if (familyName) {
+ resolved_family_name = familyName;
+ } else {
+ return NULL;
+ }
+
+ {
+ SkAutoMutexAcquire ac(global_fc_map_lock);
+ FcInit();
+ }
+
+ // At this point, we have a resolved_family_name from somewhere
+ SkASSERT(resolved_family_name);
+
+ const int bold = style & SkTypeface::kBold ?
+ FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL;
+ const int italic = style & SkTypeface::kItalic ?
+ FC_SLANT_ITALIC : FC_SLANT_ROMAN;
+ FcPattern* match = FontMatch(FC_FULLNAME, FcTypeString, resolved_family_name,
+ FC_WEIGHT, FcTypeInteger, bold,
+ FC_SLANT, FcTypeInteger, italic,
+ NULL);
+ if (face_match)
+ FcPatternDestroy(face_match);
+
+ if (!match)
+ return NULL;
+
+ FcChar8* filename;
+ if (FcPatternGetString(match, FC_FILE, 0, &filename) != FcResultMatch) {
+ FcPatternDestroy(match);
+ return NULL;
+ }
+ // Now @filename is pointing into @match
+
+ const unsigned fileid = FileIdFromFilename(reinterpret_cast<char*>(filename));
+ const unsigned id = FileIdAndStyleToUniqueId(fileid, style);
+ SkTypeface* typeface = SkNEW_ARGS(FontConfigTypeface, (style, id));
+ FcPatternDestroy(match);
+ return typeface;
+}
+
+SkTypeface* SkFontHost::ResolveTypeface(uint32_t id)
+{
+ SkAutoMutexAcquire ac(global_fc_map_lock);
+ const SkTypeface::Style style = UniqueIdToStyle(id);
+ const unsigned fileid = UniqueIdToFileId(id);
+
+ std::map<unsigned, std::string>::const_iterator i =
+ global_fc_map_inverted.find(fileid);
+ if (i == global_fc_map_inverted.end())
+ return NULL;
+
+ return SkNEW_ARGS(FontConfigTypeface, (style, id));
+}
+
+SkStream* SkFontHost::OpenStream(uint32_t id)
+{
+ SkAutoMutexAcquire ac(global_fc_map_lock);
+ const unsigned fileid = UniqueIdToFileId(id);
+
+ std::map<unsigned, std::string>::const_iterator i =
+ global_fc_map_inverted.find(fileid);
+ if (i == global_fc_map_inverted.end())
+ return NULL;
+
+ return SkNEW_ARGS(SkFILEStream, (i->second.c_str()));
+}
+
+void SkFontHost::CloseStream(uint32_t fontID, SkStream* stream)
+{
+}
+
+SkTypeface* SkFontHost::CreateTypeface(SkStream* stream)
+{
+ SkASSERT(!"SkFontHost::CreateTypeface unimplemented");
+ return NULL;
+}
+
+SkTypeface* SkFontHost::Deserialize(SkStream* stream) {
+ SkASSERT(!"SkFontHost::Deserialize unimplemented");
+ return NULL;
+}
+
+void SkFontHost::Serialize(const SkTypeface*, SkWStream*) {
+ SkASSERT(!"SkFontHost::Serialize unimplemented");
+}
+
+SkScalerContext* SkFontHost::CreateFallbackScalerContext
+ (const SkScalerContext::Rec& rec) {
+ FcPattern* pattern = FcPatternCreate();
+ FcConfigSubstitute(0, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+
+ FcResult result;
+ FcPattern* match = FcFontMatch(0, pattern, &result);
+ FcPatternDestroy(pattern);
+
+ // This will fail when we have no fonts on the system.
+ SkASSERT(match);
+
+ FcChar8* filename;
+ if (FcPatternGetString(match, FC_FILE, 0, &filename) != FcResultMatch) {
+ FcPatternDestroy(match);
+ return NULL;
+ }
+ // Now @filename is pointing into @match
+
+ const unsigned id = FileIdFromFilename(reinterpret_cast<char*>(filename));
+ FcPatternDestroy(match);
+
+ SkAutoDescriptor ad(sizeof(rec) + SkDescriptor::ComputeOverhead(1));
+ SkDescriptor* desc = ad.getDesc();
+
+ desc->init();
+ SkScalerContext::Rec* newRec =
+ (SkScalerContext::Rec*)desc->addEntry(kRec_SkDescriptorTag,
+ sizeof(rec), &rec);
+ newRec->fFontID = id;
+ desc->computeChecksum();
+
+ return SkFontHost::CreateScalerContext(desc);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+size_t SkFontHost::ShouldPurgeFontCache(size_t sizeAllocatedSoFar)
+{
+ if (sizeAllocatedSoFar > kFontCacheMemoryBudget)
+ return sizeAllocatedSoFar - kFontCacheMemoryBudget;
+ else
+ return 0; // nothing to do
+}
diff --git a/webkit/port/platform/graphics/chromium/FontCacheLinux.cpp b/webkit/port/platform/graphics/chromium/FontCacheLinux.cpp
index 2163c45..7a0606c 100644
--- a/webkit/port/platform/graphics/chromium/FontCacheLinux.cpp
+++ b/webkit/port/platform/graphics/chromium/FontCacheLinux.cpp
@@ -6,17 +6,20 @@
#include "FontCache.h"
#include "AtomicString.h"
+#include "CString.h"
#include "FontDescription.h"
#include "FontPlatformData.h"
#include "Logging.h"
#include "NotImplemented.h"
+#include "SkPaint.h"
+#include "SkTypeface.h"
+#include "SkUtils.h"
+
namespace WebCore {
void FontCache::platformInit()
{
- if (!FontPlatformData::init())
- ASSERT_NOT_REACHED();
}
const SimpleFontData* FontCache::getFontDataForCharacters(const Font& font,
@@ -58,7 +61,50 @@ void FontCache::getTraitsInFamily(const AtomicString& familyName,
FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription,
const AtomicString& family)
{
- return new FontPlatformData(fontDescription, family);
+ const char* name = 0;
+ CString s;
+
+ if (family.length() == 0) {
+ static const struct {
+ FontDescription::GenericFamilyType mType;
+ const char* mName;
+ } gNames[] = {
+ { FontDescription::SerifFamily, "serif" },
+ { FontDescription::SansSerifFamily, "sans-serif" },
+ { FontDescription::MonospaceFamily, "monospace" },
+ { FontDescription::CursiveFamily, "cursive" },
+ { FontDescription::FantasyFamily, "fantasy" }
+ };
+
+ FontDescription::GenericFamilyType type = fontDescription.genericFamily();
+ for (unsigned i = 0; i < SK_ARRAY_COUNT(gNames); i++) {
+ if (type == gNames[i].mType) {
+ name = gNames[i].mName;
+ break;
+ }
+ }
+ // if we fall out of the loop, it's ok for name to still be 0
+ }
+ else { // convert the name to utf8
+ s = family.string().utf8();
+ name = s.data();
+ }
+
+ int style = SkTypeface::kNormal;
+ if (fontDescription.weight() >= FontWeightBold)
+ style |= SkTypeface::kBold;
+ if (fontDescription.italic())
+ style |= SkTypeface::kItalic;
+
+ SkTypeface* tf = SkTypeface::Create(name, (SkTypeface::Style)style);
+
+ FontPlatformData* result =
+ new FontPlatformData(tf,
+ fontDescription.computedSize(),
+ (style & SkTypeface::kBold) && !tf->isBold(),
+ (style & SkTypeface::kItalic) && !tf->isItalic());
+ tf->unref();
+ return result;
}
AtomicString FontCache::getGenericFontForScript(UScriptCode script,
diff --git a/webkit/port/platform/graphics/chromium/FontLinux.cpp b/webkit/port/platform/graphics/chromium/FontLinux.cpp
index 2c186d1..230e31a 100644
--- a/webkit/port/platform/graphics/chromium/FontLinux.cpp
+++ b/webkit/port/platform/graphics/chromium/FontLinux.cpp
@@ -5,64 +5,58 @@
#include "config.h"
#include "Font.h"
-#include <pango/pango.h>
-#include <pango/pangoft2.h>
-
#include "FloatRect.h"
+#include "GlyphBuffer.h"
+#include "GraphicsContext.h"
#include "NotImplemented.h"
#include "PlatformContextSkia.h"
-#include "GraphicsContext.h"
#include "SimpleFontData.h"
-#include "GlyphBuffer.h"
+
+#include "SkCanvas.h"
+#include "SkPaint.h"
+#include "SkTemplates.h"
+#include "SkTypeface.h"
+#include "SkUtils.h"
namespace WebCore {
-// -----------------------------------------------------------------------------
-// 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)
-{
+void Font::drawGlyphs(GraphicsContext* gc, const SimpleFontData* font,
+ const GlyphBuffer& glyphBuffer, int from, int numGlyphs,
+ const FloatPoint& point) const {
+ SkCanvas* canvas = gc->platformContext()->canvas();
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* ctx, const SimpleFontData* sfd,
- const GlyphBuffer& glyphBuffer, int from, int to,
- const FloatPoint& point) const
-{
- // 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;
+ font->platformData().setupPaint(&paint);
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ paint.setColor(gc->fillColor().rgb());
+
+ SkASSERT(sizeof(GlyphBufferGlyph) == sizeof(uint16_t)); // compile-time assert
+
+ const GlyphBufferGlyph* glyphs = glyphBuffer.glyphs(from);
+ SkScalar x = SkFloatToScalar(point.x());
+ SkScalar y = SkFloatToScalar(point.y());
+
+ // TODO(port): Android WebCore has patches for PLATFORM(SGL) which involves
+ // this, however we don't have these patches and it's unclear when Android
+ // may upstream them.
+#if 0
+ if (glyphBuffer.hasAdjustedWidths()) {
+ const GlyphBufferAdvance* adv = glyphBuffer.advances(from);
+ SkAutoSTMalloc<32, SkPoint> storage(numGlyphs);
+ SkPoint* pos = storage.get();
+
+ for (int i = 0; i < numGlyphs; i++) {
+ pos[i].set(x, y);
+ x += SkFloatToScalar(adv[i].width());
+ y += SkFloatToScalar(adv[i].height());
+ }
+ canvas->drawPosText(glyphs, numGlyphs << 1, pos, paint);
+ } else {
+ canvas->drawText(glyphs, numGlyphs << 1, x, y, paint);
}
+#endif
+
+ canvas->drawText(glyphs, numGlyphs << 1, x, y, paint);
}
void Font::drawComplexText(GraphicsContext* context, const TextRun& run,
@@ -78,7 +72,7 @@ float Font::floatWidthForComplexText(const TextRun& run) const
}
int Font::offsetForPositionForComplexText(const TextRun& run, int x,
- bool includePartialGlyphs) const
+ bool includePartialGlyphs) const
{
notImplemented();
return 0;
@@ -86,7 +80,7 @@ int Font::offsetForPositionForComplexText(const TextRun& run, int x,
FloatRect Font::selectionRectForComplexText(const TextRun& run,
const IntPoint& point, int h,
- int from, int to) const
+ int from, int to) const
{
notImplemented();
return FloatRect();
diff --git a/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.cpp b/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.cpp
index e14a023..be21351 100644
--- a/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.cpp
+++ b/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.cpp
@@ -5,133 +5,98 @@
#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"
+#include "SkPaint.h"
+#include "SkTypeface.h"
namespace WebCore {
-PangoFontMap* FontPlatformData::m_fontMap = 0;
-GHashTable* FontPlatformData::m_hashTable = 0;
-
-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::FontPlatformData(const FontPlatformData& src)
{
- FontPlatformData::init();
-
- CString stored_family = familyName.string().utf8();
- char const* families[] = {
- stored_family.data(),
- NULL
- };
-
- 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);
+ src.m_typeface->safeRef();
+ m_typeface = src.m_typeface;
- // 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);
- }
-
- pango_font_description_free(description);
+ m_textSize = src.m_textSize;
+ m_fakeBold = src.m_fakeBold;
+ m_fakeItalic = src.m_fakeItalic;
}
-FontPlatformData::FontPlatformData(float size, bool bold, bool oblique)
- : m_context(0)
- , m_font(0)
- , m_size(size)
- , m_syntheticBold(bold)
- , m_syntheticOblique(oblique)
+FontPlatformData::FontPlatformData(SkTypeface* tf, float textSize, bool fakeBold, bool fakeItalic)
+ : m_typeface(tf)
+ , m_textSize(textSize)
+ , m_fakeBold(fakeBold)
+ , m_fakeItalic(fakeItalic)
{
+ m_typeface->safeRef();
}
-bool FontPlatformData::init()
+FontPlatformData::FontPlatformData(const FontPlatformData& src, float textSize)
+ : m_typeface(src.m_typeface)
+ , m_textSize(textSize)
+ , m_fakeBold(src.m_fakeBold)
+ , m_fakeItalic(src.m_fakeItalic)
{
- 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);
+ m_typeface->safeRef();
+}
- 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]));
+FontPlatformData::~FontPlatformData()
+{
+ m_typeface->safeUnref();
+}
- g_free(families);
- }
+FontPlatformData& FontPlatformData::operator=(const FontPlatformData& src)
+{
+ SkRefCnt_SafeAssign(m_typeface, src.m_typeface);
- return true;
+ m_textSize = src.m_textSize;
+ m_fakeBold = src.m_fakeBold;
+ m_fakeItalic = src.m_fakeItalic;
+
+ return *this;
+}
+
+void FontPlatformData::setupPaint(SkPaint* paint) const
+{
+ const float ts = m_textSize > 0 ? m_textSize : 12;
+
+ paint->setAntiAlias(true);
+ paint->setSubpixelText(true);
+ paint->setTextSize(SkFloatToScalar(ts));
+ paint->setTypeface(m_typeface);
+ paint->setFakeBoldText(m_fakeBold);
+ paint->setTextSkewX(m_fakeItalic ? -SK_Scalar1/4 : 0);
+ paint->setTextEncoding(SkPaint::kUTF16_TextEncoding);
}
-bool FontPlatformData::isFixedPitch() const
+bool FontPlatformData::operator==(const FontPlatformData& a) 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);
+ // If either of the typeface pointers are invalid (either NULL or the
+ // special deleted value) then we test for pointer equality. Otherwise, we
+ // call SkTypeface::Equal on the valid pointers.
+ const bool typefaces_equal =
+ (m_typeface == hashTableDeletedFontValue() ||
+ a.m_typeface == hashTableDeletedFontValue() ||
+ !m_typeface || !a.m_typeface) ?
+ (m_typeface == a.m_typeface) :
+ SkTypeface::Equal(m_typeface, a.m_typeface);
+ return typefaces_equal &&
+ m_textSize == a.m_textSize &&
+ m_fakeBold == a.m_fakeBold &&
+ m_fakeItalic == a.m_fakeItalic;
}
-FontPlatformData::~FontPlatformData() {
+unsigned FontPlatformData::hash() const
+{
+ // This is taken from Android code. It is not our fault.
+ unsigned h = SkTypeface::UniqueID(m_typeface);
+ h ^= 0x01010101 * (((int)m_fakeBold << 1) | (int)m_fakeItalic);
+ h ^= *reinterpret_cast<const uint32_t *>(&m_textSize);
+ return h;
}
-bool FontPlatformData::operator==(const FontPlatformData& other) const
+bool FontPlatformData::isFixedPitch() 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;
+ notImplemented();
+ return false;
}
} // namespace WebCore
diff --git a/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.h b/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.h
index b8ae94f..0d67b24 100644
--- a/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.h
+++ b/webkit/port/platform/graphics/chromium/FontPlatformDataLinux.h
@@ -8,17 +8,23 @@
#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>
+class SkPaint;
+class SkTypeface;
+
namespace WebCore {
class FontDescription;
+// -----------------------------------------------------------------------------
+// FontPlatformData is the handle which WebKit has on a specific face. A face
+// is the tuple of (font, size, ...etc). Here we are just wrapping a Skia
+// SkTypeface pointer and dealing with the reference counting etc.
+// -----------------------------------------------------------------------------
class FontPlatformData {
public:
// Used for deleted values in the font cache's hash tables. The hash table
@@ -27,47 +33,56 @@ public:
// 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())
+ : m_typeface(hashTableDeletedFontValue())
+ , m_textSize(0)
+ , m_fakeBold(false)
+ , m_fakeItalic(false)
{ }
FontPlatformData()
- : m_context(0)
- , m_font(0)
+ : m_typeface(0)
+ , m_textSize(0)
+ , m_fakeBold(false)
+ , m_fakeItalic(false)
{ }
- FontPlatformData(const FontDescription&, const AtomicString& family);
-
- FontPlatformData(float size, bool bold, bool oblique);
+ FontPlatformData(float textSize, bool fakeBold, bool fakeItalic)
+ : m_typeface(0)
+ , m_textSize(textSize)
+ , m_fakeBold(fakeBold)
+ , m_fakeItalic(fakeItalic)
+ { }
+ FontPlatformData(const FontPlatformData&);
+ FontPlatformData(SkTypeface *, float textSize, bool fakeBold, bool fakeItalic);
+ FontPlatformData(const FontPlatformData& src, float textSize);
~FontPlatformData();
- static bool init();
-
+ // -------------------------------------------------------------------------
+ // Return true iff this font is monospaced (i.e. every glyph has an equal x
+ // advance)
+ // -------------------------------------------------------------------------
bool isFixedPitch() const;
- float size() const { return m_size; }
- unsigned hash() const
- {
- notImplemented();
- return 0;
- }
+ // -------------------------------------------------------------------------
+ // Setup a Skia painting context to use this font.
+ // -------------------------------------------------------------------------
+ void setupPaint(SkPaint*) const;
- bool operator==(const FontPlatformData& other) const;
- bool isHashTableDeletedValue() const { return m_font == hashTableDeletedFontValue(); }
-
- static PangoFontMap* m_fontMap;
- static GHashTable* m_hashTable;
-
- PangoContext* m_context;
- PangoFont* m_font;
+ unsigned hash() const;
+ float size() const { return m_textSize; }
- float m_size;
- bool m_syntheticBold;
- bool m_syntheticOblique;
+ bool operator==(const FontPlatformData& other) const;
+ FontPlatformData& operator=(const FontPlatformData& src);
+ bool isHashTableDeletedValue() const { return m_typeface == hashTableDeletedFontValue(); }
private:
- static PangoFont* hashTableDeletedFontValue() { return reinterpret_cast<PangoFont*>(-1); }
+ SkTypeface* m_typeface;
+ float m_textSize;
+ bool m_fakeBold;
+ bool m_fakeItalic;
+
+ SkTypeface* hashTableDeletedFontValue() const { return reinterpret_cast<SkTypeface*>(-1); }
};
} // namespace WebCore
diff --git a/webkit/port/platform/graphics/chromium/GlyphPageTreeNodeLinux.cpp b/webkit/port/platform/graphics/chromium/GlyphPageTreeNodeLinux.cpp
index 1e7eb79..fd5aa4e 100644
--- a/webkit/port/platform/graphics/chromium/GlyphPageTreeNodeLinux.cpp
+++ b/webkit/port/platform/graphics/chromium/GlyphPageTreeNodeLinux.cpp
@@ -30,44 +30,43 @@
#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 "NotImplemented.h"
#include "SimpleFontData.h"
+#include "SkTemplates.h"
+#include "SkPaint.h"
+#include "SkUtils.h"
+
namespace WebCore
{
bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
- // 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)
+ if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
+ SkDebugf("%s last char is high-surrogate", __FUNCTION__);
return false;
-
- if (!fontData->m_font.m_font || fontData->m_font.m_font == reinterpret_cast<PangoFont*>(-1))
+ }
+
+ SkPaint paint;
+ fontData->platformData().setupPaint(&paint);
+ paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+
+ SkAutoSTMalloc <GlyphPage::size, uint16_t> glyphStorage(length);
+ uint16_t* glyphs = glyphStorage.get();
+ // textToGlyphs takes a byte count, not a glyph count so we multiply by two.
+ unsigned count = paint.textToGlyphs(buffer, bufferLength * 2, glyphs);
+ if (count != length) {
+ SkDebugf("%s count != length\n", __FUNCTION__);
return false;
+ }
- bool haveGlyphs = false;
+ unsigned allGlyphs = 0; // track if any of the glyphIDs are non-zero
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;
- }
+ setGlyphDataForIndex(offset + i, glyphs[i], fontData);
+ allGlyphs |= glyphs[i];
}
-
- return haveGlyphs;
+ return allGlyphs != 0;
}
} // namespace WebCore
diff --git a/webkit/port/platform/graphics/chromium/SimpleFontDataLinux.cpp b/webkit/port/platform/graphics/chromium/SimpleFontDataLinux.cpp
index 26caef8..7371275 100644
--- a/webkit/port/platform/graphics/chromium/SimpleFontDataLinux.cpp
+++ b/webkit/port/platform/graphics/chromium/SimpleFontDataLinux.cpp
@@ -2,15 +2,9 @@
// 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 "FloatRect.h"
@@ -18,66 +12,88 @@
#include "Logging.h"
#include "NotImplemented.h"
+#include "SkPaint.h"
+#include "SkTypeface.h"
+#include "SkTime.h"
+
namespace WebCore {
-// TODO(agl): only stubs
+// Smallcaps versions of fonts are 70% the size of the normal font.
+static const float kSmallCapsFraction = 0.7f;
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;
+ SkPaint paint;
+ SkPaint::FontMetrics metrics;
+
+ m_font.setupPaint(&paint);
+ paint.getFontMetrics(&metrics);
+
+ // use ceil instead of round to favor descent, given a lot of accidental
+ // clipping of descenders (e.g. 14pt 'g') in textedit fields
+ const int descent = SkScalarCeil(metrics.fDescent);
+ const int span = SkScalarRound(metrics.fDescent - metrics.fAscent);
+ const int ascent = span - descent;
+
+ m_ascent = ascent;
+ m_descent = descent;
+ m_xHeight = SkScalarToFloat(-metrics.fAscent) * 0.56f; // hack I stole from the Windows port
+ m_lineSpacing = ascent + descent;
+ m_lineGap = SkScalarRound(metrics.fLeading);
+
+ // In WebKit/WebCore/platform/graphics/SimpleFontData.cpp, m_spaceWidth is
+ // calculated for us, but we need to calculate m_maxCharWidth and
+ // m_avgCharWidth in order for text entry widgets to be sized correctly.
+ // Skia doesn't expose either of these so we calculate them ourselves
+
+ GlyphPage* glyphPageZero = GlyphPageTreeNode::getRootChild(this, 0)->page();
+ if (!glyphPageZero)
+ return;
+
+ static const UChar32 e_char = 'e';
+ static const UChar32 M_char = 'M';
+ m_avgCharWidth = widthForGlyph(glyphPageZero->glyphDataForCharacter(e_char).glyph);
+ m_maxCharWidth = widthForGlyph(glyphPageZero->glyphDataForCharacter(M_char).glyph);
}
-void SimpleFontData::platformDestroy() { }
+void SimpleFontData::platformDestroy()
+{
+ delete m_smallCapsFontData;
+}
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
{
- notImplemented();
- return NULL;
+ if (!m_smallCapsFontData) {
+ m_smallCapsFontData =
+ new SimpleFontData(FontPlatformData(m_font, fontDescription.computedSize() * kSmallCapsFraction));
+ }
+ return m_smallCapsFontData;
}
-bool SimpleFontData::containsCharacters(const UChar* characters,
- int length) const
+bool SimpleFontData::containsCharacters(const UChar* characters, int length) const
{
- 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;
+ SkPaint paint;
+ static const unsigned kMaxBufferCount = 64;
+ uint16_t glyphs[kMaxBufferCount];
+
+ m_font.setupPaint(&paint);
+ paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
+
+ while (length > 0) {
+ int n = SkMin32(length, SK_ARRAY_COUNT(glyphs));
+
+ // textToGlyphs takes a byte count so we double the character count.
+ int count = paint.textToGlyphs(characters, n * 2, glyphs);
+ for (int i = 0; i < count; i++) {
+ if (0 == glyphs[i]) {
+ return false; // missing glyph
+ }
}
- }
- pango_coverage_unref(requested);
- pango_coverage_unref(available);
-
- return result;
+ characters += n;
+ length -= n;
+ }
+ return true;
}
void SimpleFontData::determinePitch()
@@ -87,12 +103,16 @@ void SimpleFontData::determinePitch()
float SimpleFontData::platformWidthForGlyph(Glyph glyph) const
{
- PangoFont *const font = platformData().m_font;
- PangoRectangle rect;
+ SkASSERT(sizeof(glyph) == 2); // compile-time assert
+
+ SkPaint paint;
- pango_font_get_glyph_extents(font, glyph, NULL, &rect);
+ m_font.setupPaint(&paint);
- return static_cast<float>(rect.width) / PANGO_SCALE;
+ paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
+ SkScalar width = paint.measureText(&glyph, 2);
+
+ return SkScalarToFloat(width);
}
} // namespace WebCore