summaryrefslogtreecommitdiffstats
path: root/WebCore/platform/graphics/cairo
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore/platform/graphics/cairo')
-rw-r--r--WebCore/platform/graphics/cairo/CairoUtilities.cpp59
-rw-r--r--WebCore/platform/graphics/cairo/CairoUtilities.h39
-rw-r--r--WebCore/platform/graphics/cairo/ContextShadowCairo.cpp122
-rw-r--r--WebCore/platform/graphics/cairo/FontCacheFreeType.cpp133
-rw-r--r--WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp57
-rw-r--r--WebCore/platform/graphics/cairo/FontCustomPlatformData.h12
-rw-r--r--WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp157
-rw-r--r--WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h9
-rw-r--r--WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp3
-rw-r--r--WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp33
-rw-r--r--WebCore/platform/graphics/cairo/PathCairo.cpp18
-rw-r--r--WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp13
-rw-r--r--WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h4
-rw-r--r--WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp14
14 files changed, 466 insertions, 207 deletions
diff --git a/WebCore/platform/graphics/cairo/CairoUtilities.cpp b/WebCore/platform/graphics/cairo/CairoUtilities.cpp
new file mode 100644
index 0000000..8c2049f
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/CairoUtilities.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2010 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "CairoUtilities.h"
+
+#include "Color.h"
+#include <cairo.h>
+#include <wtf/Vector.h>
+
+namespace WebCore {
+
+void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr)
+{
+ cairo_set_antialias(dstCr, cairo_get_antialias(srcCr));
+
+ size_t dashCount = cairo_get_dash_count(srcCr);
+ Vector<double> dashes(dashCount);
+
+ double offset;
+ cairo_get_dash(srcCr, dashes.data(), &offset);
+ cairo_set_dash(dstCr, dashes.data(), dashCount, offset);
+ cairo_set_line_cap(dstCr, cairo_get_line_cap(srcCr));
+ cairo_set_line_join(dstCr, cairo_get_line_join(srcCr));
+ cairo_set_line_width(dstCr, cairo_get_line_width(srcCr));
+ cairo_set_miter_limit(dstCr, cairo_get_miter_limit(srcCr));
+ cairo_set_fill_rule(dstCr, cairo_get_fill_rule(srcCr));
+}
+
+void setSourceRGBAFromColor(cairo_t* context, const Color& color)
+{
+ float red, green, blue, alpha;
+ color.getRGBA(red, green, blue, alpha);
+ cairo_set_source_rgba(context, red, green, blue, alpha);
+}
+
+} // namespace WebCore
diff --git a/WebCore/platform/graphics/cairo/CairoUtilities.h b/WebCore/platform/graphics/cairo/CairoUtilities.h
new file mode 100644
index 0000000..0675b90
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/CairoUtilities.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2010 Igalia S.L.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef CairoUtilities_h
+#define CairoUtilities_h
+
+typedef struct _cairo cairo_t;
+
+namespace WebCore {
+class Color;
+
+void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr);
+void setSourceRGBAFromColor(cairo_t*, const Color&);
+
+} // namespace WebCore
+
+#endif // CairoUtilities_h
diff --git a/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp b/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp
new file mode 100644
index 0000000..4b94cb3
--- /dev/null
+++ b/WebCore/platform/graphics/cairo/ContextShadowCairo.cpp
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2010 Sencha, Inc.
+ * Copyright (C) 2010 Igalia S.L.
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "ContextShadow.h"
+
+#include "CairoUtilities.h"
+#include "Timer.h"
+#include <cairo.h>
+
+namespace WebCore {
+
+static cairo_surface_t* scratchBuffer = 0;
+static void purgeScratchBuffer()
+{
+ cairo_surface_destroy(scratchBuffer);
+ scratchBuffer = 0;
+}
+
+// ContextShadow needs a scratch image as the buffer for the blur filter.
+// Instead of creating and destroying the buffer for every operation,
+// we create a buffer which will be automatically purged via a timer.
+class PurgeScratchBufferTimer : public TimerBase {
+private:
+ virtual void fired() { purgeScratchBuffer(); }
+};
+static PurgeScratchBufferTimer purgeScratchBufferTimer;
+static void scheduleScratchBufferPurge()
+{
+ if (purgeScratchBufferTimer.isActive())
+ purgeScratchBufferTimer.stop();
+ purgeScratchBufferTimer.startOneShot(2);
+}
+
+static cairo_surface_t* getScratchBuffer(const IntSize& size)
+{
+ int width = size.width();
+ int height = size.height();
+ int scratchWidth = scratchBuffer ? cairo_image_surface_get_width(scratchBuffer) : 0;
+ int scratchHeight = scratchBuffer ? cairo_image_surface_get_height(scratchBuffer) : 0;
+
+ // We do not need to recreate the buffer if the current buffer is large enough.
+ if (scratchBuffer && scratchWidth >= width && scratchHeight >= height)
+ return scratchBuffer;
+
+ purgeScratchBuffer();
+
+ // Round to the nearest 32 pixels so we do not grow the buffer for similar sized requests.
+ width = (1 + (width >> 5)) << 5;
+ height = (1 + (height >> 5)) << 5;
+ scratchBuffer = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, width, height);
+ return scratchBuffer;
+}
+
+PlatformContext ContextShadow::beginShadowLayer(PlatformContext context, const FloatRect& layerArea)
+{
+ double x1, x2, y1, y2;
+ cairo_clip_extents(context, &x1, &y1, &x2, &y2);
+ calculateLayerBoundingRect(layerArea, IntRect(x1, y1, x2 - x1, y2 - y1));
+
+ // Don't paint if we are totally outside the clip region.
+ if (m_layerRect.isEmpty())
+ return 0;
+
+ m_layerImage = getScratchBuffer(m_layerRect.size());
+ m_layerContext = cairo_create(m_layerImage);
+
+ // Always clear the surface first.
+ cairo_set_operator(m_layerContext, CAIRO_OPERATOR_CLEAR);
+ cairo_paint(m_layerContext);
+ cairo_set_operator(m_layerContext, CAIRO_OPERATOR_OVER);
+
+ cairo_translate(m_layerContext, m_offset.width(), m_offset.height());
+ cairo_translate(m_layerContext, -m_layerRect.x(), -m_layerRect.y());
+ return m_layerContext;
+}
+
+void ContextShadow::endShadowLayer(cairo_t* cr)
+{
+ cairo_destroy(m_layerContext);
+ m_layerContext = 0;
+
+ if (m_type == BlurShadow)
+ blurLayerImage(cairo_image_surface_get_data(m_layerImage),
+ IntSize(cairo_image_surface_get_width(m_layerImage), cairo_image_surface_get_height(m_layerImage)),
+ cairo_image_surface_get_stride(m_layerImage));
+
+ cairo_save(cr);
+ setSourceRGBAFromColor(cr, m_color);
+ cairo_mask_surface(cr, m_layerImage, m_layerRect.x(), m_layerRect.y());
+ cairo_restore(cr);
+
+ // Schedule a purge of the scratch buffer. We do not need to destroy the surface.
+ scheduleScratchBufferPurge();
+}
+
+}
diff --git a/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp b/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp
index c09dd49..febad12 100644
--- a/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp
+++ b/WebCore/platform/graphics/cairo/FontCacheFreeType.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2010 Igalia S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -26,13 +27,17 @@
#include "OwnPtrCairo.h"
#include "PlatformRefPtrCairo.h"
#include "SimpleFontData.h"
+#include <cairo-ft.h>
+#include <cairo.h>
+#include <fontconfig/fcfreetype.h>
#include <wtf/Assertions.h>
namespace WebCore {
void FontCache::platformInit()
{
- if (!FontPlatformData::init())
+ // It's fine to call FcInit multiple times per the documentation.
+ if (!FcInit())
ASSERT_NOT_REACHED();
}
@@ -72,9 +77,9 @@ SimpleFontData* FontCache::getSimilarFontPlatformData(const Font& font)
SimpleFontData* FontCache::getLastResortFallbackFont(const FontDescription& fontDescription)
{
- // FIXME: Would be even better to somehow get the user's default font here.
- // For now we'll pick the default that the user would get without changing any prefs.
- static AtomicString timesStr("Times New Roman");
+ // We want to return a fallback font here, otherwise the logic preventing FontConfig
+ // matches for non-fallback fonts might return 0. See isFallbackFontAllowed.
+ static AtomicString timesStr("serif");
return getCachedFontData(fontDescription, timesStr);
}
@@ -82,54 +87,106 @@ void FontCache::getTraitsInFamily(const AtomicString& familyName, Vector<unsigne
{
}
-static bool isWellKnownFontName(const AtomicString family)
+static CString getFamilyNameStringFromFontDescriptionAndFamily(const FontDescription& fontDescription, const AtomicString& family)
{
- // Fonts that are used by layout tests included. The fact that
- // they are used in Layout Tests indicate web compatibility issues
- // if we do not handle them correctly.
- if (equalIgnoringCase(family, "sans-serif") || equalIgnoringCase(family, "sans")
- || equalIgnoringCase(family, "serif") || equalIgnoringCase(family, "mono")
- || equalIgnoringCase(family, "monospace") || equalIgnoringCase(family, "cursive")
- || equalIgnoringCase(family, "fantasy") || equalIgnoringCase(family, "Times")
- || equalIgnoringCase(family, "Courier") || equalIgnoringCase(family, "Helvetica")
- || equalIgnoringCase(family, "Arial") || equalIgnoringCase(family, "Lucida Grande")
- || equalIgnoringCase(family, "Ahem") || equalIgnoringCase(family, "Georgia")
- || equalIgnoringCase(family, "Times New Roman"))
- return true;
-
- return false;
+ // If we're creating a fallback font (e.g. "-webkit-monospace"), convert the name into
+ // the fallback name (like "monospace") that fontconfig understands.
+ if (family.length() && !family.startsWith("-webkit-"))
+ return family.string().utf8();
+
+ switch (fontDescription.genericFamily()) {
+ case FontDescription::StandardFamily:
+ case FontDescription::SerifFamily:
+ return "serif";
+ case FontDescription::SansSerifFamily:
+ return "sans-serif";
+ case FontDescription::MonospaceFamily:
+ return "monospace";
+ case FontDescription::CursiveFamily:
+ return "cursive";
+ case FontDescription::FantasyFamily:
+ return "fantasy";
+ case FontDescription::NoFamily:
+ default:
+ return "";
+ }
}
-FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
-{
- // Handle generic family types specially, because fontconfig does not know them, but we have
- // code to fallback correctly in our platform data implementation.
- if (!family.length() || family.startsWith("-webkit-")
- || (fontDescription.genericFamily() != FontDescription::NoFamily)
- || isWellKnownFontName(family))
- return new FontPlatformData(fontDescription, family);
- // First check the font exists.
- CString familyNameString = family.string().utf8();
- const char* fcfamily = familyNameString.data();
+static bool isFallbackFontAllowed(const CString& familyName)
+{
+ return !strcasecmp(familyName.data(), "sans")
+ || !strcasecmp(familyName.data(), "sans-serif")
+ || !strcasecmp(familyName.data(), "serif")
+ || !strcasecmp(familyName.data(), "monospace");
+}
+FontPlatformData* FontCache::createFontPlatformData(const FontDescription& fontDescription, const AtomicString& family)
+{
+ // The CSS font matching algorithm (http://www.w3.org/TR/css3-fonts/#font-matching-algorithm)
+ // says that we must find an exact match for font family, slant (italic or oblique can be used)
+ // and font weight (we only match bold/non-bold here).
PlatformRefPtr<FcPattern> pattern = adoptPlatformRef(FcPatternCreate());
- if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily)))
+ CString familyNameString = getFamilyNameStringFromFontDescriptionAndFamily(fontDescription, family);
+ if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(familyNameString.data())))
return 0;
- OwnPtr<FcObjectSet> objectSet(FcObjectSetCreate());
- if (!FcObjectSetAdd(objectSet.get(), FC_FAMILY))
+ bool italic = fontDescription.italic();
+ if (!FcPatternAddInteger(pattern.get(), FC_SLANT, italic ? FC_SLANT_ITALIC : FC_SLANT_ROMAN))
+ return 0;
+ bool bold = fontDescription.weight() >= FontWeightBold;
+ if (!FcPatternAddInteger(pattern.get(), FC_WEIGHT, bold ? FC_WEIGHT_BOLD : FC_WEIGHT_NORMAL))
+ return 0;
+ if (!FcPatternAddDouble(pattern.get(), FC_PIXEL_SIZE, fontDescription.computedPixelSize()))
return 0;
- OwnPtr<FcFontSet> fontSet(FcFontList(0, pattern.get(), objectSet.get()));
-
- if (!fontSet)
+ // The following comment and strategy are originally from Skia (src/ports/SkFontHost_fontconfig.cpp):
+ // Font matching:
+ // CSS often specifies a fallback list of families:
+ // font-family: a, b, c, serif;
+ // However, fontconfig will always do its best to find *a* font when asked
+ // for something so we need a way to tell if the match which it has found is
+ // "good enough" for us. Otherwise, we can return null which gets piped up
+ // and lets WebKit know to try the next CSS family name. However, fontconfig
+ // configs allow substitutions (mapping "Arial -> Helvetica" etc) and we
+ // wish to support that.
+ //
+ // Thus, if a specific family is requested we set @family_requested. Then we
+ // record two strings: the family name after config processing and the
+ // family name after resolving. If the two are equal, it's a good match.
+ //
+ // So consider the case where a user has mapped Arial to Helvetica in their
+ // config.
+ // requested family: "Arial"
+ // post_config_family: "Helvetica"
+ // post_match_family: "Helvetica"
+ // -> good match
+ //
+ // and for a missing font:
+ // requested family: "Monaco"
+ // post_config_family: "Monaco"
+ // post_match_family: "Times New Roman"
+ // -> BAD match
+ //
+ FcConfigSubstitute(0, pattern.get(), FcMatchPattern);
+ FcDefaultSubstitute(pattern.get());
+
+ FcChar8* familyNameAfterConfiguration;
+ FcPatternGetString(pattern.get(), FC_FAMILY, 0, &familyNameAfterConfiguration);
+
+ FcResult fontConfigResult;
+ PlatformRefPtr<FcPattern> resultPattern = adoptPlatformRef(FcFontMatch(0, pattern.get(), &fontConfigResult));
+ if (!resultPattern) // No match.
return 0;
- if (!fontSet->fonts)
+ // Properly handle the situation where Fontconfig gives us a font that has a different family than we requested.
+ FcChar8* familyNameAfterMatching;
+ FcPatternGetString(resultPattern.get(), FC_FAMILY, 0, &familyNameAfterMatching);
+ if (strcasecmp(reinterpret_cast<char*>(familyNameAfterConfiguration),
+ reinterpret_cast<char*>(familyNameAfterMatching)) && !isFallbackFontAllowed(familyNameString))
return 0;
- return new FontPlatformData(fontDescription, family);
+ return new FontPlatformData(resultPattern.get(), fontDescription);
}
}
diff --git a/WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp b/WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp
index 6b76c2a..0d195cb 100644
--- a/WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp
+++ b/WebCore/platform/graphics/cairo/FontCustomPlatformData.cpp
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2010 Igalia S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -23,11 +24,37 @@
#include "FontPlatformData.h"
#include "SharedBuffer.h"
+#include <cairo-ft.h>
+#include <cairo.h>
namespace WebCore {
+static void releaseCustomFontData(void* data)
+{
+ static_cast<SharedBuffer*>(data)->deref();
+}
+
+FontCustomPlatformData::FontCustomPlatformData(FT_Face freeTypeFace, SharedBuffer* buffer)
+ : m_freeTypeFace(freeTypeFace)
+ , m_fontFace(cairo_ft_font_face_create_for_ft_face(freeTypeFace, 0))
+{
+ // FIXME Should we be setting some hinting options here?
+
+ buffer->ref(); // This is balanced by the buffer->deref() in releaseCustomFontData.
+ static cairo_user_data_key_t bufferKey;
+ cairo_font_face_set_user_data(m_fontFace, &bufferKey, buffer,
+ static_cast<cairo_destroy_func_t>(releaseCustomFontData));
+
+ // Cairo doesn't do FreeType reference counting, so we need to ensure that when
+ // this cairo_font_face_t is destroyed, it cleans up the FreeType face as well.
+ static cairo_user_data_key_t freeTypeFaceKey;
+ cairo_font_face_set_user_data(m_fontFace, &freeTypeFaceKey, freeTypeFace,
+ reinterpret_cast<cairo_destroy_func_t>(FT_Done_Face));
+}
+
FontCustomPlatformData::~FontCustomPlatformData()
{
+ // m_freeTypeFace will be destroyed along with m_fontFace. See the constructor.
cairo_font_face_destroy(m_fontFace);
}
@@ -36,38 +63,20 @@ FontPlatformData FontCustomPlatformData::fontPlatformData(int size, bool bold, b
return FontPlatformData(m_fontFace, size, bold, italic);
}
-static void releaseData(void* data)
-{
- static_cast<SharedBuffer*>(data)->deref();
-}
-
FontCustomPlatformData* createFontCustomPlatformData(SharedBuffer* buffer)
{
ASSERT_ARG(buffer, buffer);
- int error;
-
static FT_Library library = 0;
- if (!library) {
- error = FT_Init_FreeType(&library);
- if (error) {
- library = 0;
- return 0;
- }
+ if (!library && FT_Init_FreeType(&library)) {
+ library = 0;
+ return 0;
}
- FT_Face face;
- error = FT_New_Memory_Face(library, reinterpret_cast<const FT_Byte*>(buffer->data()), buffer->size(), 0, &face);
- if (error)
+ FT_Face freeTypeFace;
+ if (FT_New_Memory_Face(library, reinterpret_cast<const FT_Byte*>(buffer->data()), buffer->size(), 0, &freeTypeFace))
return 0;
-
- buffer->ref();
- cairo_font_face_t* fontFace = cairo_ft_font_face_create_for_ft_face(face, 0);
-
- static cairo_user_data_key_t bufferKey;
- cairo_font_face_set_user_data(fontFace, &bufferKey, buffer, releaseData);
-
- return new FontCustomPlatformData(fontFace);
+ return new FontCustomPlatformData(freeTypeFace, buffer);
}
bool FontCustomPlatformData::supportsFormat(const String& format)
diff --git a/WebCore/platform/graphics/cairo/FontCustomPlatformData.h b/WebCore/platform/graphics/cairo/FontCustomPlatformData.h
index a72a6a4..c48d110 100644
--- a/WebCore/platform/graphics/cairo/FontCustomPlatformData.h
+++ b/WebCore/platform/graphics/cairo/FontCustomPlatformData.h
@@ -1,5 +1,6 @@
/*
* Copyright (C) 2008 Alp Toker <alp@atoker.com>
+ * Copyright (C) 2010 Igalia S.L.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
@@ -25,6 +26,7 @@
#include <wtf/Forward.h>
#include <wtf/Noncopyable.h>
+typedef struct FT_FaceRec_* FT_Face;
typedef struct _cairo_font_face cairo_font_face_t;
namespace WebCore {
@@ -33,16 +35,14 @@ class FontPlatformData;
class SharedBuffer;
struct FontCustomPlatformData : Noncopyable {
- FontCustomPlatformData(cairo_font_face_t* fontFace)
- : m_fontFace(fontFace)
- {}
-
+public:
+ FontCustomPlatformData(FT_Face, SharedBuffer*);
~FontCustomPlatformData();
-
FontPlatformData fontPlatformData(int size, bool bold, bool italic, FontRenderingMode = NormalRenderingMode);
-
static bool supportsFormat(const String&);
+private:
+ FT_Face m_freeTypeFace;
cairo_font_face_t* m_fontFace;
};
diff --git a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp
index 7968966..0617e6c 100644
--- a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp
+++ b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.cpp
@@ -3,7 +3,7 @@
* Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
* Copyright (C) 2007, 2008 Alp Toker <alp@atoker.com>
* Copyright (C) 2007 Holger Hans Peter Freyther
- * Copyright (C) 2009 Igalia S.L.
+ * Copyright (C) 2009, 2010 Igalia S.L.
* All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -27,100 +27,88 @@
#include "PlatformString.h"
#include "FontDescription.h"
-#include <wtf/text/CString.h>
-
#include <cairo-ft.h>
#include <cairo.h>
#include <fontconfig/fcfreetype.h>
+
#if !PLATFORM(EFL) || ENABLE(GLIB_SUPPORT)
#include <gdk/gdk.h>
#endif
namespace WebCore {
-FontPlatformData::FontPlatformData(const FontDescription& fontDescription, const AtomicString& familyName)
- : m_fallbacks(0)
+cairo_subpixel_order_t convertFontConfigSubpixelOrder(int fontConfigOrder)
+{
+ switch (fontConfigOrder) {
+ case FC_RGBA_RGB:
+ return CAIRO_SUBPIXEL_ORDER_RGB;
+ case FC_RGBA_BGR:
+ return CAIRO_SUBPIXEL_ORDER_BGR;
+ case FC_RGBA_VRGB:
+ return CAIRO_SUBPIXEL_ORDER_VRGB;
+ case FC_RGBA_VBGR:
+ return CAIRO_SUBPIXEL_ORDER_VBGR;
+ case FC_RGBA_NONE:
+ case FC_RGBA_UNKNOWN:
+ return CAIRO_SUBPIXEL_ORDER_DEFAULT;
+ }
+ return CAIRO_SUBPIXEL_ORDER_DEFAULT;
+}
+
+cairo_hint_style_t convertFontConfigHintStyle(int fontConfigStyle)
+{
+ switch (fontConfigStyle) {
+ case FC_HINT_NONE:
+ return CAIRO_HINT_STYLE_NONE;
+ case FC_HINT_SLIGHT:
+ return CAIRO_HINT_STYLE_SLIGHT;
+ case FC_HINT_MEDIUM:
+ return CAIRO_HINT_STYLE_MEDIUM;
+ case FC_HINT_FULL:
+ return CAIRO_HINT_STYLE_FULL;
+ }
+ return CAIRO_HINT_STYLE_NONE;
+}
+
+void setCairoFontOptionsFromFontConfigPattern(cairo_font_options_t* options, FcPattern* pattern)
+{
+ FcBool booleanResult;
+ int integerResult;
+
+ // We will determine if subpixel anti-aliasing is enabled via the FC_RGBA setting.
+ if (FcPatternGetBool(pattern, FC_ANTIALIAS, 0, &booleanResult) == FcResultMatch && booleanResult)
+ cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_GRAY);
+
+ if (FcPatternGetInteger(pattern, FC_RGBA, 0, &integerResult) == FcResultMatch) {
+ if (integerResult != FC_RGBA_NONE)
+ cairo_font_options_set_antialias(options, CAIRO_ANTIALIAS_SUBPIXEL);
+ cairo_font_options_set_subpixel_order(options, convertFontConfigSubpixelOrder(integerResult));
+ }
+
+ if (FcPatternGetInteger(pattern, FC_HINT_STYLE, 0, &integerResult) == FcResultMatch)
+ cairo_font_options_set_hint_style(options, convertFontConfigHintStyle(integerResult));
+
+ if (FcPatternGetBool(pattern, FC_HINTING, 0, &booleanResult) == FcResultMatch && !booleanResult)
+ cairo_font_options_set_hint_style(options, CAIRO_HINT_STYLE_NONE);
+}
+
+FontPlatformData::FontPlatformData(FcPattern* pattern, const FontDescription& fontDescription)
+ : m_pattern(pattern)
+ , m_fallbacks(0)
, m_size(fontDescription.computedPixelSize())
, m_syntheticBold(false)
, m_syntheticOblique(false)
{
- FontPlatformData::init();
-
- CString familyNameString = familyName.string().utf8();
- const char* fcfamily = familyNameString.data();
- int fcslant = FC_SLANT_ROMAN;
- // FIXME: Map all FontWeight values to fontconfig weights.
- int fcweight = FC_WEIGHT_NORMAL;
- double fcsize = fontDescription.computedPixelSize();
- if (fontDescription.italic())
- fcslant = FC_SLANT_ITALIC;
- if (fontDescription.weight() >= FontWeight600)
- fcweight = FC_WEIGHT_BOLD;
-
- int type = fontDescription.genericFamily();
-
- PlatformRefPtr<FcPattern> pattern = adoptPlatformRef(FcPatternCreate());
- cairo_font_face_t* fontFace;
- static const cairo_font_options_t* defaultOptions = cairo_font_options_create();
- const cairo_font_options_t* options = NULL;
- cairo_matrix_t fontMatrix;
-
- if (!FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily)))
- return;
-
- switch (type) {
- case FontDescription::SerifFamily:
- fcfamily = "serif";
- break;
- case FontDescription::SansSerifFamily:
- fcfamily = "sans-serif";
- break;
- case FontDescription::MonospaceFamily:
- fcfamily = "monospace";
- break;
- case FontDescription::StandardFamily:
- fcfamily = "sans-serif";
- break;
- case FontDescription::NoFamily:
- default:
- fcfamily = NULL;
- break;
- }
+ cairo_font_options_t* options = cairo_font_options_create();
+ setCairoFontOptionsFromFontConfigPattern(options, pattern);
- if (fcfamily && !FcPatternAddString(pattern.get(), FC_FAMILY, reinterpret_cast<const FcChar8*>(fcfamily)))
- return;
- if (!FcPatternAddInteger(pattern.get(), FC_WEIGHT, fcweight))
- return;
- if (!FcPatternAddInteger(pattern.get(), FC_SLANT, fcslant))
- return;
- if (!FcPatternAddDouble(pattern.get(), FC_PIXEL_SIZE, fcsize))
- return;
-
- FcConfigSubstitute(0, pattern.get(), FcMatchPattern);
- FcDefaultSubstitute(pattern.get());
-
- FcResult fcresult;
- m_pattern = adoptPlatformRef(FcFontMatch(0, pattern.get(), &fcresult));
- // FIXME: should we set some default font?
- if (!m_pattern)
- return;
- fontFace = cairo_ft_font_face_create_for_pattern(m_pattern.get());
+ cairo_matrix_t fontMatrix;
+ cairo_matrix_init_scale(&fontMatrix, m_size, m_size);
cairo_matrix_t ctm;
- cairo_matrix_init_scale(&fontMatrix, fontDescription.computedPixelSize(), fontDescription.computedPixelSize());
cairo_matrix_init_identity(&ctm);
-#if !PLATFORM(EFL) || ENABLE(GLIB_SUPPORT)
- if (GdkScreen* screen = gdk_screen_get_default())
-gdk_screen_get_font_options(screen);
-#endif
-
- // gdk_screen_get_font_options() returns NULL if no default options are
- // set, so we always have to check.
- if (!options)
- options = defaultOptions;
-
- m_scaledFont = adoptPlatformRef(cairo_scaled_font_create(fontFace, &fontMatrix, &ctm, options));
- cairo_font_face_destroy(fontFace);
+ PlatformRefPtr<cairo_font_face_t> fontFace = adoptPlatformRef(cairo_ft_font_face_create_for_pattern(m_pattern.get()));
+ m_scaledFont = adoptPlatformRef(cairo_scaled_font_create(fontFace.get(), &fontMatrix, &ctm, options));
}
FontPlatformData::FontPlatformData(float size, bool bold, bool italic)
@@ -184,19 +172,6 @@ FontPlatformData::FontPlatformData(const FontPlatformData& other)
*this = other;
}
-bool FontPlatformData::init()
-{
- static bool initialized = false;
- if (initialized)
- return true;
- if (!FcInit()) {
- fprintf(stderr, "Can't init font config library\n");
- return false;
- }
- initialized = true;
- return true;
-}
-
FontPlatformData::~FontPlatformData()
{
if (m_fallbacks) {
diff --git a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h
index 987a684..f3488ef 100644
--- a/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h
+++ b/WebCore/platform/graphics/cairo/FontPlatformDataFreeType.h
@@ -3,6 +3,7 @@
* Copyright (C) 2006 Michael Emmel mike.emmel@gmail.com
* Copyright (C) 2007 Holger Hans Peter Freyther
* Copyright (C) 2007 Pioneer Research Center USA, Inc.
+ * Copyright (C) 2010 Igalia S.L.
* All rights reserved.
*
* This library is free software; you can redistribute it and/or
@@ -29,11 +30,10 @@
#include "GlyphBuffer.h"
#include "HashFunctions.h"
#include "PlatformRefPtrCairo.h"
-#include <cairo-ft.h>
-#include <cairo.h>
-#include <fontconfig/fcfreetype.h>
#include <wtf/Forward.h>
+typedef struct _FcFontSet FcFontSet;
+
namespace WebCore {
class FontPlatformData {
@@ -53,14 +53,13 @@ public:
, m_syntheticOblique(false)
{ }
- FontPlatformData(const FontDescription&, const AtomicString& family);
+ FontPlatformData(FcPattern*, const FontDescription&);
FontPlatformData(cairo_font_face_t* fontFace, float size, bool bold, bool italic);
FontPlatformData(float size, bool bold, bool italic);
FontPlatformData(const FontPlatformData&);
~FontPlatformData();
- static bool init();
bool isFixedPitch();
float size() const { return m_size; }
void setSize(float size) { m_size = size; }
diff --git a/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp b/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp
index 26da68d..66e9c16 100644
--- a/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GlyphPageTreeNodeCairo.cpp
@@ -32,6 +32,9 @@
#include "GlyphPageTreeNode.h"
#include "SimpleFontData.h"
+#include <cairo-ft.h>
+#include <cairo.h>
+#include <fontconfig/fcfreetype.h>
namespace WebCore {
diff --git a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
index 5de7e1f..05096a9 100644
--- a/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
+++ b/WebCore/platform/graphics/cairo/GraphicsContextCairo.cpp
@@ -35,6 +35,7 @@
#include "AffineTransform.h"
#include "CairoPath.h"
+#include "CairoUtilities.h"
#include "FEGaussianBlur.h"
#include "FloatRect.h"
#include "Font.h"
@@ -131,28 +132,10 @@ static inline void fillRectSourceOver(cairo_t* cr, const FloatRect& rect, const
cairo_fill(cr);
}
-static inline void copyContextProperties(cairo_t* srcCr, cairo_t* dstCr)
-{
- cairo_set_antialias(dstCr, cairo_get_antialias(srcCr));
-
- size_t dashCount = cairo_get_dash_count(srcCr);
- Vector<double> dashes(dashCount);
-
- double offset;
- cairo_get_dash(srcCr, dashes.data(), &offset);
- cairo_set_dash(dstCr, dashes.data(), dashCount, offset);
- cairo_set_line_cap(dstCr, cairo_get_line_cap(srcCr));
- cairo_set_line_join(dstCr, cairo_get_line_join(srcCr));
- cairo_set_line_width(dstCr, cairo_get_line_width(srcCr));
- cairo_set_miter_limit(dstCr, cairo_get_miter_limit(srcCr));
- cairo_set_fill_rule(dstCr, cairo_get_fill_rule(srcCr));
-}
-
static void appendPathToCairoContext(cairo_t* to, cairo_t* from)
{
- cairo_path_t* cairoPath = cairo_copy_path(from);
- cairo_append_path(to, cairoPath);
- cairo_path_destroy(cairoPath);
+ OwnPtr<cairo_path_t> cairoPath(cairo_copy_path(from));
+ cairo_append_path(to, cairoPath.get());
}
// We apply the pending path built via addPath to the Cairo context
@@ -1182,9 +1165,8 @@ void GraphicsContext::clip(const Path& path)
return;
cairo_t* cr = m_data->cr;
- cairo_path_t* p = cairo_copy_path(path.platformPath()->context());
- cairo_append_path(cr, p);
- cairo_path_destroy(p);
+ OwnPtr<cairo_path_t> p(cairo_copy_path(path.platformPath()->context()));
+ cairo_append_path(cr, p.get());
cairo_fill_rule_t savedFillRule = cairo_get_fill_rule(cr);
cairo_set_fill_rule(cr, CAIRO_FILL_RULE_WINDING);
cairo_clip(cr);
@@ -1341,9 +1323,8 @@ void GraphicsContext::drawTiledShadow(const IntRect& rect, const FloatSize& topL
copyContextProperties(cr, shadowContext);
cairo_translate(shadowContext, -rect.x() + blurRadius, -rect.y() + blurRadius);
cairo_new_path(shadowContext);
- cairo_path_t* path = cairo_copy_path(cr);
- cairo_append_path(shadowContext, path);
- cairo_path_destroy(path);
+ OwnPtr<cairo_path_t> path(cairo_copy_path(cr));
+ cairo_append_path(shadowContext, path.get());
setPlatformFill(this, shadowContext, m_common);
diff --git a/WebCore/platform/graphics/cairo/PathCairo.cpp b/WebCore/platform/graphics/cairo/PathCairo.cpp
index 05c6952..776bceb 100644
--- a/WebCore/platform/graphics/cairo/PathCairo.cpp
+++ b/WebCore/platform/graphics/cairo/PathCairo.cpp
@@ -29,9 +29,9 @@
#include "CairoPath.h"
#include "FloatRect.h"
#include "GraphicsContext.h"
+#include "OwnPtrCairo.h"
#include "PlatformString.h"
#include "StrokeStyleApplier.h"
-
#include <cairo.h>
#include <math.h>
#include <wtf/MathExtras.h>
@@ -52,9 +52,8 @@ Path::Path(const Path& other)
: m_path(new CairoPath())
{
cairo_t* cr = platformPath()->context();
- cairo_path_t* p = cairo_copy_path(other.platformPath()->context());
- cairo_append_path(cr, p);
- cairo_path_destroy(p);
+ OwnPtr<cairo_path_t> p(cairo_copy_path(other.platformPath()->context()));
+ cairo_append_path(cr, p.get());
}
Path& Path::operator=(const Path& other)
@@ -64,9 +63,8 @@ Path& Path::operator=(const Path& other)
clear();
cairo_t* cr = platformPath()->context();
- cairo_path_t* p = cairo_copy_path(other.platformPath()->context());
- cairo_append_path(cr, p);
- cairo_path_destroy(p);
+ OwnPtr<cairo_path_t> p(cairo_copy_path(other.platformPath()->context()));
+ cairo_append_path(cr, p.get());
return *this;
}
@@ -297,7 +295,7 @@ bool Path::strokeContains(StrokeStyleApplier* applier, const FloatPoint& point)
void Path::apply(void* info, PathApplierFunction function) const
{
cairo_t* cr = platformPath()->context();
- cairo_path_t* path = cairo_copy_path(cr);
+ OwnPtr<cairo_path_t> path(cairo_copy_path(cr));
cairo_path_data_t* data;
PathElement pelement;
FloatPoint points[3];
@@ -329,7 +327,6 @@ void Path::apply(void* info, PathApplierFunction function) const
break;
}
}
- cairo_path_destroy(path);
}
void Path::transform(const AffineTransform& trans)
@@ -346,7 +343,7 @@ String Path::debugString() const
return String();
String pathString;
- cairo_path_t* path = cairo_copy_path(platformPath()->context());
+ OwnPtr<cairo_path_t> path(cairo_copy_path(platformPath()->context()));
cairo_path_data_t* data;
for (int i = 0; i < path->num_data; i += path->data[i].header.length) {
@@ -373,7 +370,6 @@ String Path::debugString() const
}
}
- cairo_path_destroy(path);
return pathString.simplifyWhiteSpace();
}
diff --git a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp
index aa466f9..d289585 100644
--- a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp
+++ b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.cpp
@@ -54,6 +54,19 @@ template <> void derefPlatformPtr(cairo_surface_t* ptr)
cairo_surface_destroy(ptr);
}
+template <> cairo_font_face_t* refPlatformPtr(cairo_font_face_t* ptr)
+{
+ if (ptr)
+ cairo_font_face_reference(ptr);
+ return ptr;
+}
+
+template <> void derefPlatformPtr(cairo_font_face_t* ptr)
+{
+ if (ptr)
+ cairo_font_face_destroy(ptr);
+}
+
template <> cairo_scaled_font_t* refPlatformPtr(cairo_scaled_font_t* ptr)
{
if (ptr)
diff --git a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h
index 4b45c1b..3b720c6 100644
--- a/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h
+++ b/WebCore/platform/graphics/cairo/PlatformRefPtrCairo.h
@@ -24,6 +24,7 @@
typedef struct _cairo cairo_t;
typedef struct _cairo_surface cairo_surface_t;
+typedef struct _cairo_font_face cairo_font_face_t;
typedef struct _cairo_scaled_font cairo_scaled_font_t;
#if defined(USE_FREETYPE)
@@ -38,6 +39,9 @@ template <> void derefPlatformPtr(cairo_t* ptr);
template <> cairo_surface_t* refPlatformPtr(cairo_surface_t* ptr);
template <> void derefPlatformPtr(cairo_surface_t* ptr);
+template <> cairo_font_face_t* refPlatformPtr(cairo_font_face_t*);
+template <> void derefPlatformPtr(cairo_font_face_t*);
+
template <> cairo_scaled_font_t* refPlatformPtr(cairo_scaled_font_t*);
template <> void derefPlatformPtr(cairo_scaled_font_t*);
diff --git a/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp
index fd85d6f..3d7c34b 100644
--- a/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp
+++ b/WebCore/platform/graphics/cairo/SimpleFontDataCairo.cpp
@@ -38,7 +38,9 @@
#include "FontCache.h"
#include "FontDescription.h"
#include "GlyphBuffer.h"
+#include <cairo-ft.h>
#include <cairo.h>
+#include <fontconfig/fcfreetype.h>
#include <wtf/MathExtras.h>
namespace WebCore {
@@ -81,12 +83,12 @@ void SimpleFontData::platformDestroy()
SimpleFontData* SimpleFontData::smallCapsFontData(const FontDescription& fontDescription) const
{
- if (!m_smallCapsFontData) {
- FontDescription desc = FontDescription(fontDescription);
- desc.setComputedSize(0.70f * fontDescription.computedSize());
- FontPlatformData platformData(desc, desc.family().family());
- m_smallCapsFontData = new SimpleFontData(platformData);
- }
+ // FIXME: I think we want to ask FontConfig for the right font again.
+ if (!m_smallCapsFontData)
+ m_smallCapsFontData = new SimpleFontData(
+ FontPlatformData(cairo_scaled_font_get_font_face(m_platformData.scaledFont()),
+ 0.70f * fontDescription.computedSize(), m_platformData.syntheticBold(), m_platformData.syntheticOblique()));
+
return m_smallCapsFontData;
}