diff options
Diffstat (limited to 'WebCore/platform/graphics/cairo')
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; } |