Commit 4683e2a7 authored by bdash's avatar bdash

2007-01-18 Mitz Pettel <mitz@webkit.org>

        Reviewed by Darin.

        - fix http://bugs.webkit.org/show_bug.cgi?id=6218
          CSS1: WebTextRenderer caches and re-uses fallback renderers that are based on family lists

        This patch takes character-to-glyph mapping out of FontData and instead makes
        each Font keep its own mapping, using a shared set of glyph page fallback trees.

        For each page number there is (at most) one tree. A path from the root to a
        node in the tree corresponds to a fallback list of FontDatas. The node points to
        a page (which may be shared with other nodes) that maps each character in its range
        to a glyph in the first FontData in the fallback list that has it, or to 0 if none of
        the FontDatas has a glyph for that character. A special kind of node, that can
        only occur as a leaf, corresponds to using system fallback fonts after the list
        has been exhausted. This prevents system fallback from polluting non-leaf
        nodes.

        Nodes and pages are initialized lazily and employ "copy on write".

        * CMakeLists.txt:
        * WebCore.pro:
        * WebCore.vcproj/WebCore/WebCore.vcproj:
        * WebCore.xcodeproj/project.pbxproj:
        * WebCoreSources.bkl:
        * platform/Font.cpp:
        (WebCore::WidthIterator::WidthIterator): Removed substituteFontData.
        (WebCore::WidthIterator::advance): Moved all character-to-glyph mapping logic out
        of here and replaced it with a call to Font::glyphDataForCharacter().
        (WebCore::Font::Font):
        (WebCore::Font::operator=):
        (WebCore::Font::glyphDataForCharacter): Added. This method performs the lookup in the
        page fallback trees, triggering lazy initialization as needed, and caching pointers to
        the retrieved page tree nodes in the font.
        (WebCore::Font::update):
        (WebCore::Font::drawSimpleText):
        (WebCore::Font::floatWidth):
        (WebCore::Font::floatWidthForSimpleText): Removed substituteFont argument.
        (WebCore::Font::offsetForPositionForSimpleText):
        * platform/Font.h:
        * platform/FontData.cpp:
        (WebCore::FontData::FontData):
        * platform/FontData.h:
        (WebCore::FontData::missingGlyphData): Added. Returns the "missing glyph" GlyphData for
        this FontData.
        * platform/GlyphMap.cpp: Removed.
        * platform/GlyphMap.h: Removed.
        * platform/GlyphPageTreeNode.cpp: Renamed GlyphMap.cpp to this.
        (WebCore::GlyphPageTreeNode::getRoot): Added. Returns the root of the page fallback tree for
        the given page number.
        (WebCore::GlyphPageTreeNode::initializePage): Added. Helper method that initializes the page
        pointer of a node, possibly to a pointer to another node's page or to 0.
        (WebCore::GlyphPageTreeNode::getChild): Added.
        * platform/GlyphPageTreeNode.h: Renamed GlyphMap.h to this.
        (WebCore::GlyphPage::glyphDataForCharacter):
        (WebCore::GlyphPage::setGlyphDataForCharacter):
        (WebCore::GlyphPage::setGlyphDataForIndex):
        (WebCore::GlyphPageTreeNode::GlyphPageTreeNode):
        (WebCore::GlyphPageTreeNode::getRootChild):
        (WebCore::GlyphPageTreeNode::parent):
        (WebCore::GlyphPageTreeNode::page):
        (WebCore::GlyphPageTreeNode::level):
        (WebCore::GlyphPageTreeNode::isSystemFallback): Added. Returns whether the node corresponds
        to the system providing fallback fonts, which is done on a character-by-character basis.
        * platform/gdk/GlyphMapGdk.cpp: Removed.
        * platform/gdk/GlyphPageTreeNodeGdk.cpp: Renamed GlyphMapGdk.cpp to this.
        (WebCore::GlyphPage::fill):
        * platform/mac/FontDataMac.mm:
        (WebCore::FontData::platformInit):
        * platform/mac/FontMac.mm:
        (WebCore::Font::Font):
        * platform/mac/GlyphMapMac.cpp: Removed.
        * platform/mac/GlyphPageTreeNodeMac.cpp: Renamed GlypMapMac.cpp to this.
        (WebCore::GlyphPage::fill): Changed to return false if the font has no glyphs in the page.
        * platform/qt/GlyphMapQt.cpp: Removed.
        * platform/qt/GlyphPageTreeNodeQt.cpp: Renamed GlyphMapQt.cpp to this.
        (WebCore::GlyphPage::fill):
        * platform/win/GlyphMapWin.cpp: Removed.
        * platform/win/GlyphPageTreeNodeWin.cpp: Renamed GlyphMapWin to this.
        (WebCore::GlyphPage::fill):


git-svn-id: svn://svn.chromium.org/blink/trunk@18966 bbb929c8-8fbe-4397-9dbb-9b2b20218538
parent d48e142c
......@@ -997,7 +997,7 @@ set(WebCore_SRCS
platform/FontData.cpp
platform/FontFallbackList.cpp
platform/FontFamily.cpp
platform/GlyphMap.cpp
platform/GlyphPageTreeNode.cpp
platform/GlyphWidthMap.cpp
platform/KURL.cpp
platform/Logging.cpp
......@@ -1167,7 +1167,7 @@ set(WebCore_SRCS
platform/qt/FontQt.cpp
platform/qt/FrameQtClient.cpp
platform/qt/FrameQt.cpp
platform/qt/GlyphMapQt.cpp
platform/qt/GlyphPageTreeNodeQt.cpp
platform/qt/LoaderFunctionsQt.cpp
platform/qt/MimeTypeRegistryQt.cpp
platform/qt/PageQt.cpp
......
2007-01-18 Mitz Pettel <mitz@webkit.org>
Reviewed by Darin.
- fix http://bugs.webkit.org/show_bug.cgi?id=6218
CSS1: WebTextRenderer caches and re-uses fallback renderers that are based on family lists
This patch takes character-to-glyph mapping out of FontData and instead makes
each Font keep its own mapping, using a shared set of glyph page fallback trees.
For each page number there is (at most) one tree. A path from the root to a
node in the tree corresponds to a fallback list of FontDatas. The node points to
a page (which may be shared with other nodes) that maps each character in its range
to a glyph in the first FontData in the fallback list that has it, or to 0 if none of
the FontDatas has a glyph for that character. A special kind of node, that can
only occur as a leaf, corresponds to using system fallback fonts after the list
has been exhausted. This prevents system fallback from polluting non-leaf
nodes.
Nodes and pages are initialized lazily and employ "copy on write".
* CMakeLists.txt:
* WebCore.pro:
* WebCore.vcproj/WebCore/WebCore.vcproj:
* WebCore.xcodeproj/project.pbxproj:
* WebCoreSources.bkl:
* platform/Font.cpp:
(WebCore::WidthIterator::WidthIterator): Removed substituteFontData.
(WebCore::WidthIterator::advance): Moved all character-to-glyph mapping logic out
of here and replaced it with a call to Font::glyphDataForCharacter().
(WebCore::Font::Font):
(WebCore::Font::operator=):
(WebCore::Font::glyphDataForCharacter): Added. This method performs the lookup in the
page fallback trees, triggering lazy initialization as needed, and caching pointers to
the retrieved page tree nodes in the font.
(WebCore::Font::update):
(WebCore::Font::drawSimpleText):
(WebCore::Font::floatWidth):
(WebCore::Font::floatWidthForSimpleText): Removed substituteFont argument.
(WebCore::Font::offsetForPositionForSimpleText):
* platform/Font.h:
* platform/FontData.cpp:
(WebCore::FontData::FontData):
* platform/FontData.h:
(WebCore::FontData::missingGlyphData): Added. Returns the "missing glyph" GlyphData for
this FontData.
* platform/GlyphMap.cpp: Removed.
* platform/GlyphMap.h: Removed.
* platform/GlyphPageTreeNode.cpp: Renamed GlyphMap.cpp to this.
(WebCore::GlyphPageTreeNode::getRoot): Added. Returns the root of the page fallback tree for
the given page number.
(WebCore::GlyphPageTreeNode::initializePage): Added. Helper method that initializes the page
pointer of a node, possibly to a pointer to another node's page or to 0.
(WebCore::GlyphPageTreeNode::getChild): Added.
* platform/GlyphPageTreeNode.h: Renamed GlyphMap.h to this.
(WebCore::GlyphPage::glyphDataForCharacter):
(WebCore::GlyphPage::setGlyphDataForCharacter):
(WebCore::GlyphPage::setGlyphDataForIndex):
(WebCore::GlyphPageTreeNode::GlyphPageTreeNode):
(WebCore::GlyphPageTreeNode::getRootChild):
(WebCore::GlyphPageTreeNode::parent):
(WebCore::GlyphPageTreeNode::page):
(WebCore::GlyphPageTreeNode::level):
(WebCore::GlyphPageTreeNode::isSystemFallback): Added. Returns whether the node corresponds
to the system providing fallback fonts, which is done on a character-by-character basis.
* platform/gdk/GlyphMapGdk.cpp: Removed.
* platform/gdk/GlyphPageTreeNodeGdk.cpp: Renamed GlyphMapGdk.cpp to this.
(WebCore::GlyphPage::fill):
* platform/mac/FontDataMac.mm:
(WebCore::FontData::platformInit):
* platform/mac/FontMac.mm:
(WebCore::Font::Font):
* platform/mac/GlyphMapMac.cpp: Removed.
* platform/mac/GlyphPageTreeNodeMac.cpp: Renamed GlypMapMac.cpp to this.
(WebCore::GlyphPage::fill): Changed to return false if the font has no glyphs in the page.
* platform/qt/GlyphMapQt.cpp: Removed.
* platform/qt/GlyphPageTreeNodeQt.cpp: Renamed GlyphMapQt.cpp to this.
(WebCore::GlyphPage::fill):
* platform/win/GlyphMapWin.cpp: Removed.
* platform/win/GlyphPageTreeNodeWin.cpp: Renamed GlyphMapWin to this.
(WebCore::GlyphPage::fill):
2007-01-18 Mitz Pettel <mitz@webkit.org>
Reviewed by Darin.
......
......@@ -561,7 +561,7 @@ SOURCES += \
platform/graphics/qt/AffineTransformQt.cpp \
platform/qt/StringQt.cpp \
platform/graphics/qt/ColorQt.cpp \
platform/qt/GlyphMapQt.cpp \
platform/qt/GlyphPageTreeNodeQt.cpp \
platform/qt/CookieJarQt.cpp \
platform/qt/FontPlatformDataQt.cpp \
platform/qt/ScrollViewQt.cpp \
......@@ -614,7 +614,7 @@ SOURCES += \
platform/FontCache.cpp \
platform/FontFallbackList.cpp \
platform/RegularExpression.cpp \
platform/GlyphMap.cpp \
platform/GlyphPageTreeNode.cpp \
platform/Font.cpp \
platform/FontData.cpp \
rendering/HitTestResult.cpp \
......
......@@ -1523,11 +1523,11 @@
>
</File>
<File
RelativePath="..\..\platform\GlyphMap.cpp"
RelativePath="..\..\platform\GlyphPageTreeNode.cpp"
>
</File>
<File
RelativePath="..\..\platform\GlyphMap.h"
RelativePath="..\..\platform\GlyphPageTreeNode.h"
>
</File>
<File
......@@ -2854,7 +2854,7 @@
>
</File>
<File
RelativePath="..\..\platform\win\GlyphMapWin.cpp"
RelativePath="..\..\platform\win\GlyphPageTreeNodeWin.cpp"
>
</File>
<File
......
......@@ -2689,9 +2689,9 @@
BC6DABF30A19015700E5CD14 /* FontCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC6DABF20A19015700E5CD14 /* FontCache.cpp */; };
BC6DADEF0A195FDF00E5CD14 /* WebFontCache.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6DADEE0A195FDF00E5CD14 /* WebFontCache.h */; };
BC6DADFA0A19602B00E5CD14 /* WebFontCache.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC6DADF90A19602B00E5CD14 /* WebFontCache.mm */; };
BC6DB3690A1A7CB700E5CD14 /* GlyphMap.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6DB3680A1A7CB700E5CD14 /* GlyphMap.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC6DB4740A1A90FB00E5CD14 /* GlyphMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC6DB4730A1A90FB00E5CD14 /* GlyphMap.cpp */; };
BC6DB4D40A1AFEEF00E5CD14 /* GlyphMapMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC6DB4D30A1AFEEF00E5CD14 /* GlyphMapMac.cpp */; };
BC6DB3690A1A7CB700E5CD14 /* GlyphPageTreeNode.h in Headers */ = {isa = PBXBuildFile; fileRef = BC6DB3680A1A7CB700E5CD14 /* GlyphPageTreeNode.h */; settings = {ATTRIBUTES = (Private, ); }; };
BC6DB4740A1A90FB00E5CD14 /* GlyphPageTreeNode.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC6DB4730A1A90FB00E5CD14 /* GlyphPageTreeNode.cpp */; };
BC6DB4D40A1AFEEF00E5CD14 /* GlyphPageTreeNodeMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC6DB4D30A1AFEEF00E5CD14 /* GlyphPageTreeNodeMac.cpp */; };
BCAA90C30A7EBA60008B1229 /* ScrollBar.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCAA90C20A7EBA60008B1229 /* ScrollBar.cpp */; };
BCB16B8B0979B01400467741 /* DeprecatedArray.h in Headers */ = {isa = PBXBuildFile; fileRef = BCB16B880979B01400467741 /* DeprecatedArray.h */; settings = {ATTRIBUTES = (Private, ); }; };
BCB16B8C0979B01400467741 /* ArrayImpl.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BCB16B890979B01400467741 /* ArrayImpl.cpp */; };
......@@ -5811,9 +5811,9 @@
BC6DABF20A19015700E5CD14 /* FontCache.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FontCache.cpp; sourceTree = "<group>"; };
BC6DADEE0A195FDF00E5CD14 /* WebFontCache.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = WebFontCache.h; sourceTree = "<group>"; };
BC6DADF90A19602B00E5CD14 /* WebFontCache.mm */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.objcpp; path = WebFontCache.mm; sourceTree = "<group>"; };
BC6DB3680A1A7CB700E5CD14 /* GlyphMap.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GlyphMap.h; sourceTree = "<group>"; };
BC6DB4730A1A90FB00E5CD14 /* GlyphMap.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = GlyphMap.cpp; sourceTree = "<group>"; };
BC6DB4D30A1AFEEF00E5CD14 /* GlyphMapMac.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = GlyphMapMac.cpp; sourceTree = "<group>"; };
BC6DB3680A1A7CB700E5CD14 /* GlyphPageTreeNode.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = GlyphPageTreeNode.h; sourceTree = "<group>"; };
BC6DB4730A1A90FB00E5CD14 /* GlyphPageTreeNode.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = GlyphPageTreeNode.cpp; sourceTree = "<group>"; };
BC6DB4D30A1AFEEF00E5CD14 /* GlyphPageTreeNodeMac.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = GlyphPageTreeNodeMac.cpp; sourceTree = "<group>"; };
BC7B2AF80450824100A8000F /* ScrollBar.h */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.c.h; path = ScrollBar.h; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
BC7B2AF90450824100A8000F /* PlatformScrollBarMac.mm */ = {isa = PBXFileReference; fileEncoding = 30; indentWidth = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PlatformScrollBarMac.mm; sourceTree = "<group>"; tabWidth = 8; usesTabs = 0; };
BCAA90C20A7EBA60008B1229 /* ScrollBar.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; name = ScrollBar.cpp; path = platform/ScrollBar.cpp; sourceTree = SOURCE_ROOT; };
......@@ -6716,7 +6716,7 @@
BCEB377209B7BA3900CB38B1 /* FontMac.mm */,
148A00100AF59F3F008CC700 /* FontPlatformData.h */,
935C476C09AC4D6300A6AAB4 /* FoundationExtras.h */,
BC6DB4D30A1AFEEF00E5CD14 /* GlyphMapMac.cpp */,
BC6DB4D30A1AFEEF00E5CD14 /* GlyphPageTreeNodeMac.cpp */,
935C476E09AC4D7300A6AAB4 /* KeyEventMac.mm */,
6593923909AE435C002C531F /* KURLMac.mm */,
9352084409BD43B900F2038D /* Language.mm */,
......@@ -8937,8 +8937,8 @@
BCC47E2409A3D6F100ADB771 /* FontFamily.cpp */,
BCC47E2509A3D6F100ADB771 /* FontFamily.h */,
BCC71A120A0FF94D0014EE6E /* GlyphBuffer.h */,
BC6DB4730A1A90FB00E5CD14 /* GlyphMap.cpp */,
BC6DB3680A1A7CB700E5CD14 /* GlyphMap.h */,
BC6DB4730A1A90FB00E5CD14 /* GlyphPageTreeNode.cpp */,
BC6DB3680A1A7CB700E5CD14 /* GlyphPageTreeNode.h */,
BCC089550A1C4CC9006189A6 /* GlyphWidthMap.cpp */,
BCC089290A1C4991006189A6 /* GlyphWidthMap.h */,
6593923509AE4346002C531F /* KURL.cpp */,
......@@ -10048,7 +10048,7 @@
A80E73500A199C77007FB8C5 /* StyleBase.h in Headers */,
A80E73510A199C77007FB8C5 /* StyleList.h in Headers */,
A80E73520A199C77007FB8C5 /* CSSSelector.h in Headers */,
BC6DB3690A1A7CB700E5CD14 /* GlyphMap.h in Headers */,
BC6DB3690A1A7CB700E5CD14 /* GlyphPageTreeNode.h in Headers */,
A80E7A180A19C3D6007FB8C5 /* JSHTMLMetaElement.h in Headers */,
A80E7B0C0A19D606007FB8C5 /* JSHTMLTitleElement.h in Headers */,
A80E7B0D0A19D606007FB8C5 /* JSHTMLLinkElement.h in Headers */,
......@@ -11619,8 +11619,8 @@
A80E7E9E0A1A83E3007FB8C5 /* JSHTMLTextAreaElement.cpp in Sources */,
A80E7EA00A1A83E3007FB8C5 /* JSHTMLButtonElement.cpp in Sources */,
A826EC480A1B0CBE00CD1BB6 /* JSHTMLOptionElementConstructor.cpp in Sources */,
BC6DB4740A1A90FB00E5CD14 /* GlyphMap.cpp in Sources */,
BC6DB4D40A1AFEEF00E5CD14 /* GlyphMapMac.cpp in Sources */,
BC6DB4740A1A90FB00E5CD14 /* GlyphPageTreeNode.cpp in Sources */,
BC6DB4D40A1AFEEF00E5CD14 /* GlyphPageTreeNodeMac.cpp in Sources */,
1A9EF4570A1B957D00332B63 /* JSCanvasRenderingContext2DCustom.cpp in Sources */,
BCC088860A1BD78D006189A6 /* FontDataMac.mm in Sources */,
BCC0891A0A1C4652006189A6 /* FontData.cpp in Sources */,
......@@ -148,7 +148,7 @@
platform/FontData.cpp
platform/FontFallbackList.cpp
platform/FontFamily.cpp
platform/GlyphMap.cpp
platform/GlyphPageTreeNode.cpp
platform/GlyphWidthMap.cpp
platform/KURL.cpp
platform/Logging.cpp
......@@ -191,7 +191,7 @@
platform/win/FontDataWin.cpp
platform/win/FontPlatformDataWin.cpp
platform/win/FontWin.cpp
platform/win/GlyphMapWin.cpp
platform/win/GlyphPageTreeNodeWin.cpp
platform/win/IntPointWin.cpp
platform/win/IntRectWin.cpp
platform/win/IntSizeWin.cpp
......
......@@ -27,6 +27,7 @@
#define Font_h
#include "FontDescription.h"
#include <wtf/HashMap.h>
#if PLATFORM(QT)
class QFont;
......@@ -40,10 +41,13 @@ class FontData;
class FontFallbackList;
class FontPlatformData;
class GlyphBuffer;
class GlyphPageTreeNode;
class GraphicsContext;
class IntPoint;
class TextStyle;
struct GlyphData;
class TextRun {
public:
TextRun(const UChar* c, int len)
......@@ -148,6 +152,8 @@ public:
const FontData* primaryFont() const;
const FontData* fontDataAt(unsigned) const;
const GlyphData& glyphDataForCharacter(UChar32, const UChar* cluster, unsigned clusterLength, bool mirror, bool attemptFontSubstitution) const;
// Used for complex text, and does not utilize the glyph map cache.
const FontData* fontDataForCharacters(const UChar*, int length) const;
private:
......@@ -156,8 +162,7 @@ private:
void drawSimpleText(GraphicsContext*, const TextRun&, const TextStyle&, const FloatPoint&) const;
void drawGlyphs(GraphicsContext*, const FontData*, const GlyphBuffer&, int from, int to, const FloatPoint&) const;
void drawComplexText(GraphicsContext*, const TextRun&, const TextStyle&, const FloatPoint&) const;
float floatWidthForSimpleText(const TextRun&, const TextStyle&, const FontData* substituteFontData,
float* startX, GlyphBuffer*) const;
float floatWidthForSimpleText(const TextRun&, const TextStyle&, float* startX, GlyphBuffer*) const;
float floatWidthForComplexText(const TextRun&, const TextStyle&) const;
int offsetForPositionForSimpleText(const TextRun&, const TextStyle&, int position, bool includePartialGlyphs) const;
int offsetForPositionForComplexText(const TextRun&, const TextStyle&, int position, bool includePartialGlyphs) const;
......@@ -182,6 +187,8 @@ public:
private:
FontDescription m_fontDescription;
mutable RefPtr<FontFallbackList> m_fontList;
mutable HashMap<int, GlyphPageTreeNode*> m_pages;
mutable GlyphPageTreeNode* m_pageZero;
short m_letterSpacing;
short m_wordSpacing;
};
......
......@@ -44,11 +44,13 @@ FontData::FontData(const FontPlatformData& f)
// Nasty hack to determine if we should round or ceil space widths.
// If the font is monospace or fake monospace we ceil to ensure that
// every character and the space are the same width. Otherwise we round.
m_spaceGlyph = m_characterToGlyphMap.glyphDataForCharacter(' ', this).glyph;
m_spaceGlyph = GlyphPageTreeNode::getRootChild(this, 0)->page()->glyphDataForCharacter(' ').glyph;
float width = widthForGlyph(m_spaceGlyph);
m_spaceWidth = width;
determinePitch();
m_adjustedSpaceWidth = m_treatAsFixedPitch ? ceilf(width) : roundf(width);
m_missingGlyphData.fontData = this;
m_missingGlyphData.glyph = 0;
}
FontData::~FontData()
......
......@@ -24,7 +24,7 @@
#define FontData_h
#include "FontPlatformData.h"
#include "GlyphMap.h"
#include "GlyphPageTreeNode.h"
#include "GlyphWidthMap.h"
#include <wtf/Noncopyable.h>
......@@ -65,10 +65,8 @@ public:
void determinePitch();
Pitch pitch() const { return m_treatAsFixedPitch ? FixedPitch : VariablePitch; }
// FIXME: Should go away when we pull the glyph map out of the FontData.
GlyphData glyphDataForCharacter(UChar32 c) const { return m_characterToGlyphMap.glyphDataForCharacter(c, this); }
void setGlyphDataForCharacter(UChar32 c, Glyph glyph, const FontData* fontData) const { m_characterToGlyphMap.setGlyphDataForCharacter(c, glyph, fontData); }
const GlyphData& missingGlyphData() const { return m_missingGlyphData; }
#if PLATFORM(MAC)
NSFont* getNSFont() const { return m_font.font; }
......@@ -95,7 +93,6 @@ public:
float m_xHeight;
FontPlatformData m_font;
mutable GlyphMap m_characterToGlyphMap;
mutable GlyphWidthMap m_glyphToWidthMap;
bool m_treatAsFixedPitch;
......@@ -103,6 +100,8 @@ public:
float m_spaceWidth;
float m_adjustedSpaceWidth;
GlyphData m_missingGlyphData;
mutable FontData* m_smallCapsFontData;
#if PLATFORM(CG)
......
/*
* Copyright (C) 2006 Apple Computer, Inc. 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.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 "GlyphMap.h"
#include "CharacterNames.h"
#include "FontData.h"
#include <wtf/unicode/Unicode.h>
namespace WebCore {
GlyphData GlyphMap::glyphDataForCharacter(UChar32 c, const FontData* fontData)
{
unsigned pageNumber = (c / GlyphPage::size);
GlyphPage* page = locatePage(pageNumber, fontData);
if (page)
return page->glyphDataForCharacter(c);
GlyphData data = { 0, fontData };
return data;
}
void GlyphMap::setGlyphDataForCharacter(UChar32 c, Glyph glyph, const FontData* fontData)
{
unsigned pageNumber = (c / GlyphPage::size);
GlyphPage* page = locatePage(pageNumber, fontData);
if (page)
page->setGlyphDataForCharacter(c, glyph, fontData);
}
inline GlyphMap::GlyphPage* GlyphMap::locatePage(unsigned pageNumber, const FontData* fontData)
{
GlyphPage* page;
if (pageNumber == 0) {
if (m_filledPrimaryPage)
return &m_primaryPage;
page = &m_primaryPage;
} else {
if (m_pages) {
GlyphPage* result = m_pages->get(pageNumber);
if (result)
return result;
}
page = new GlyphPage;
}
unsigned start = pageNumber * GlyphPage::size;
UChar buffer[GlyphPage::size * 2 + 2];
unsigned bufferLength;
unsigned i;
// Fill in a buffer with the entire "page" of characters that we want to look up glyphs for.
if (start < 0x10000) {
bufferLength = GlyphPage::size;
for (i = 0; i < GlyphPage::size; i++)
buffer[i] = start + i;
if (start == 0) {
// Control characters must not render at all.
for (i = 0; i < 0x20; ++i)
buffer[i] = zeroWidthSpace;
for (i = 0x7F; i < 0xA0; i++)
buffer[i] = zeroWidthSpace;
// \n, \t, and nonbreaking space must render as a space.
buffer[(int)'\n'] = ' ';
buffer[(int)'\t'] = ' ';
buffer[noBreakSpace] = ' ';
}
} else {
bufferLength = GlyphPage::size * 2;
for (i = 0; i < GlyphPage::size; i++) {
int c = i + start;
buffer[i * 2] = U16_LEAD(c);
buffer[i * 2 + 1] = U16_TRAIL(c);
}
}
// Now that we have a buffer full of characters, we want to get back an array
// of glyph indices. This part involves calling into the platform-specific
// routine of our glyph map for actually filling in the page with the glyphs.
bool success = fillPage(page, buffer, bufferLength, fontData);
if (!success) {
if (pageNumber != 0)
delete page;
return 0;
}
if (pageNumber == 0)
m_filledPrimaryPage = true;
else {
if (!m_pages)
m_pages = new HashMap<int, GlyphPage*>;
m_pages->set(pageNumber, page);
}
return page;
}
}
/*
* Copyright (C) 2006 Apple Computer, Inc. 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.
* 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 OR ITS 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 "GlyphPageTreeNode.h"
#include "CharacterNames.h"
#include "FontData.h"
#include <wtf/unicode/Unicode.h>
namespace WebCore {
GlyphPageTreeNode* GlyphPageTreeNode::getRoot(unsigned pageNumber)
{
static HashMap<int, GlyphPageTreeNode*> roots;
static GlyphPageTreeNode* pageZeroRoot;
GlyphPageTreeNode* node = pageNumber ? roots.get(pageNumber) : pageZeroRoot;
if (!node) {
node = new GlyphPageTreeNode;
#ifndef NDEBUG
node->m_pageNumber = pageNumber;
#endif
if (pageNumber)
roots.set(pageNumber, node);
else
pageZeroRoot = node;
}
return node;
}
void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNumber)
{
ASSERT(!m_page);
GlyphPage* parentPage = m_parent->m_page;
if (fontData) {
if (m_level == 1) {
// Children of the root hold pure pages.
unsigned start = pageNumber * GlyphPage::size;
UChar buffer[GlyphPage::size * 2 + 2];
unsigned bufferLength;
unsigned i;
// Fill in a buffer with the entire "page" of characters that we want to look up glyphs for.
if (start < 0x10000) {
bufferLength = GlyphPage::size;
for (i = 0; i < GlyphPage::size; i++)
buffer[i] = start + i;
if (start == 0) {
// Control characters must not render at all.
for (i = 0; i < 0x20; ++i)
buffer[i] = zeroWidthSpace;
for (i = 0x7F; i < 0xA0; i++)
buffer[i] = zeroWidthSpace;
// \n, \t, and nonbreaking space must render as a space.
buffer[(int)'\n'] = ' ';
buffer[(int)'\t'] = ' ';
buffer[noBreakSpace] = ' ';
}
} else {
bufferLength = GlyphPage::size * 2;
for (i = 0; i < GlyphPage::size; i++) {
int c = i + start;
buffer[i * 2] = U16_LEAD(c);
buffer[i * 2 + 1] = U16_TRAIL(c);
}
}
m_page = new GlyphPage(this);
// Now that we have a buffer full of characters, we want to get back an array
// of glyph indices. This part involves calling into the platform-specific
// routine of our glyph map for actually filling in the page with the glyphs.
// Success is not guaranteed. For example, Times fails to fill page 260, giving glyph data
// for only 128 out of 256 characters.
bool haveGlyphs = m_page->fill(buffer, bufferLength, fontData);
if (!haveGlyphs) {
delete m_page;
m_page = 0;
}
} else if (parentPage && parentPage->owner() != m_parent)
// Ensures that the overlay page is owned by the child of the owner of the
// parent page, and therefore will be shared.
m_page = parentPage->owner()->getChild(fontData, pageNumber)->page();
else {
// Get the pure page for the fallback font.
GlyphPage* fallbackPage = getRootChild(fontData, pageNumber)->page();
if (!parentPage)
m_page = fallbackPage;
else if (!fallbackPage) {
m_page = parentPage;
} else {
m_page = new GlyphPage(this);
// Overlay the parent page on the fallback page. Check if the fallback font
// has added anything.
bool newGlyphs = false;
for (unsigned i = 0; i < GlyphPage::size; i++) {
if (parentPage->m_glyphs[i].glyph)
m_page->m_glyphs[i] = parentPage->m_glyphs[i];
else if (fallbackPage->m_glyphs[i].glyph) {
m_page->m_glyphs[i] = fallbackPage->m_glyphs[i];
newGlyphs = true;
} else {
const GlyphData data = { 0, 0 };
m_page->m_glyphs[i] = data;
}
}
if (!newGlyphs) {
delete m_page;
m_page = parentPage;
}
}
}
} else {
m_page = new GlyphPage(this);
// System fallback. Initialized with the parent's page here, as individual
// entries may use different fonts depending on character.
if (parentPage)
memcpy(m_page->m_glyphs, parentPage->m_glyphs, GlyphPage::size * sizeof(m_page->m_glyphs[0]));
else {
const GlyphData data = { 0, 0 };
for (unsigned i = 0; i < GlyphPage::size; i++)
m_page->m_glyphs[i] = data;
}
}
}
GlyphPageTreeNode* GlyphPageTreeNode::getChild(const FontData* fontData, unsigned pageNumber)
{
ASSERT(fontData || !m_isSystemFallback);
ASSERT(pageNumber == m_pageNumber);
GlyphPageTreeNode* child = fontData ? m_children.get(fontData) : m_systemFallbackChild;
if (!child) {
child = new GlyphPageTreeNode;
child->m_parent = this;
child->m_level = m_level + 1;
#ifndef NDEBUG
child->m_pageNumber = m_pageNumber;
#endif
if (fontData)
m_children.set(fontData, child);
else {
m_systemFallbackChild = child;
child->m_isSystemFallback = true;
}
child->initializePage(fontData, pageNumber);
}
return child;
}
}
......@@ -36,6 +36,7 @@
namespace WebCore {
class FontData;
class GlyphPageTreeNode;
typedef unsigned short Glyph;
......@@ -44,39 +45,77 @@ struct GlyphData {
const FontData* fontData;
};
class GlyphMap : Noncopyable {
struct GlyphPage {
GlyphPage()
: m_owner(0)
{
}
GlyphPage(GlyphPageTreeNode* owner)
: m_owner(owner)
{
}
static const size_t size = 256; // Covers Latin-1 in a single page.
GlyphData m_glyphs[size];
GlyphPageTreeNode* m_owner;
const GlyphData& glyphDataForCharacter(UChar32 c) const { return m_glyphs[c % size]; }
void setGlyphDataForCharacter(UChar32 c, Glyph g, const FontData* f)
{
setGlyphDataForIndex(c % size, g, f);
}
void setGlyphDataForIndex(unsigned index, Glyph g, const FontData* f)
{
m_glyphs[index].glyph = g;
m_glyphs[index].fontData = f;
}
GlyphPageTreeNode* owner() const { return m_owner; }
// Implemented by the platform.
bool fill(UChar* characterBuffer, unsigned bufferLength, const FontData* fontData);
};
class GlyphPageTreeNode {
public:
GlyphMap() : m_filledPrimaryPage(false), m_pages(0) {}
~GlyphMap() { if (m_pages) { deleteAllValues(*m_pages); delete m_pages; } }
GlyphPageTreeNode()
: m_parent(0)
, m_page(0)
, m_level(0)
, m_isSystemFallback(false)
, m_systemFallbackChild(0)
#ifndef NDEBUG
, m_pageNumber(0)
#endif
{
}
GlyphData glyphDataForCharacter(UChar32, const FontData*);
void setGlyphDataForCharacter(UChar32, Glyph, const FontData*);
static GlyphPageTreeNode* getRootChild(const FontData* fontData, unsigned pageNumber)
{
return getRoot(pageNumber)->getChild(fontData, pageNumber);
}
GlyphPageTreeNode* parent() const { return m_parent; }
GlyphPageTreeNode* getChild(const FontData*, unsigned pageNumber);
GlyphPage* page() const { return m_page; }
unsigned level() const { return m_level; }
bool isSystemFallback() const { return m_isSystemFallback; }
private:
struct GlyphPage {
static const size_t size = 256; // Covers Latin-1 in a single page.
GlyphData m_glyphs[size];
const GlyphData& glyphDataForCharacter(UChar32 c) const { return m_glyphs[c % size]; }
void setGlyphDataForCharacter(UChar32 c, Glyph g, const FontData* f)
{
setGlyphDataForIndex(c % size, g, f);
}
void setGlyphDataForIndex(unsigned index, Glyph g, const FontData* f)
{
m_glyphs[index].glyph = g;
m_glyphs[index].fontData = f;
}
};
GlyphPage* locatePage(unsigned page, const FontData* fontData);
bool fillPage(GlyphPage*, UChar* characterBuffer, unsigned bufferLength, const FontData* fontData);
bool m_filledPrimaryPage;
GlyphPage m_primaryPage; // We optimize for the page that contains Latin-1.
HashMap<int, GlyphPage*>* m_pages;
static GlyphPageTreeNode* getRoot(unsigned pageNumber);
void initializePage(const FontData*, unsigned pageNumber);
GlyphPageTreeNode* m_parent;
GlyphPage* m_page;
unsigned m_level;
bool m_isSystemFallback;
HashMap<const FontData*, GlyphPageTreeNode*> m_children;
GlyphPageTreeNode* m_systemFallbackChild;
#ifndef NDEBUG
unsigned m_pageNumber;
#endif
};
}
} // namespace WebCore
#endif
#endif // GlyphPageTreeNode_h
......@@ -29,16 +29,16 @@
*/
#include "config.h"
#include "GlyphMap.h"
#include "GlyphPageTreeNode.h"
#include "FontData.h"
namespace WebCore {
bool GlyphMap::fillPage(GlyphPage* page, UChar* buffer, unsigned bufferLength, const FontData* fontData)
bool GlyphPage::fill(UChar* buffer, unsigned bufferLength, const FontData* fontData)
{
for (unsigned i = 0; i < bufferLength; i++)
page->setGlyphDataForIndex(i, fontData->getGlyphIndex(buffer[i]), fontData);
setGlyphDataForIndex(i, fontData->getGlyphIndex(buffer[i]), fontData);
return true;
}
......
......@@ -180,7 +180,7 @@ void FontData::platformInit()
// Measure the actual character "x", because AppKit synthesizes X height rather than getting it from the font.
// Unfortunately, NSFont will round this for us so we don't quite get the right value.
NSGlyph xGlyph = m_characterToGlyphMap.glyphDataForCharacter('x', this).glyph;
NSGlyph xGlyph = GlyphPageTreeNode::getRootChild(this, 0)->page()->glyphDataForCharacter('x').glyph;
if (xGlyph) {
NSRect xBox = [m_font.font boundingRectForGlyph:xGlyph];
// Use the maximum of either width or height because "x" is nearly square
......
......@@ -421,7 +421,9 @@ static void disposeATSULayoutParameters(ATSULayoutParameters *params)
}
Font::Font(const FontPlatformData& fontData, bool isPrinterFont)
:m_letterSpacing(0), m_wordSpacing(0)
: m_pageZero(0)
, m_letterSpacing(0)
, m_wordSpacing(0)
{
m_fontDescription.setUsePrinterFont(isPrinterFont);
m_fontList = new FontFallbackList();
......
......@@ -27,7 +27,7 @@
*/
#include "config.h"
#include "GlyphMap.h"
#include "GlyphPageTreeNode.h"
#include "FontData.h"
#include "WebCoreSystemInterface.h"
......@@ -35,7 +35,7 @@
namespace WebCore {
bool GlyphMap::fillPage(GlyphPage* page, UChar* buffer, unsigned bufferLength, const FontData* fontData)
bool GlyphPage::fill(UChar* buffer, unsigned bufferLength, const FontData* fontData)
{
// Use an array of long so we get good enough alignment.
long glyphVector[(GLYPH_VECTOR_SIZE + sizeof(long) - 1) / sizeof(long)];
......@@ -56,14 +56,18 @@ bool GlyphMap::fillPage(GlyphPage* page, UChar* buffer, unsigned bufferLength, c
return false;
}
bool haveGlyphs = false;
ATSLayoutRecord* glyphRecord = (ATSLayoutRecord*)wkGetGlyphVectorFirstRecord(glyphVector);
for (unsigned i = 0; i < GlyphPage::size; i++) {
page->setGlyphDataForIndex(i, glyphRecord->glyphID, fontData);
Glyph glyph = glyphRecord->glyphID;
setGlyphDataForIndex(i, glyph, fontData);
if (!haveGlyphs && glyph)
haveGlyphs = true;
glyphRecord = (ATSLayoutRecord *)((char *)glyphRecord + wkGetGlyphVectorRecordSize(glyphVector));
}
wkClearGlyphVector(&glyphVector);
return true;
return haveGlyphs;
}
} // namespace WebCore
......@@ -28,7 +28,7 @@
*/
#include "config.h"
#include "GlyphMap.h"
#include "GlyphPageTreeNode.h"
#include "FontData.h"
#include <wtf/unicode/Unicode.h>
......@@ -36,7 +36,7 @@
namespace WebCore {
bool GlyphMap::fillPage(GlyphPage* page, UChar* buffer, unsigned bufferLength, const FontData* fontData)
bool GlyphPage::fill(UChar* buffer, unsigned bufferLength, const FontData* fontData)
{
bool isUtf16 = bufferLength != GlyphPage::size;
......@@ -51,7 +51,7 @@ bool GlyphMap::fillPage(GlyphPage* page, UChar* buffer, unsigned bufferLength, c
character = buffer[i];
}
page->setGlyphDataForIndex(i, character, fontData);
setGlyphDataForIndex(i, character, fontData);
}
return true;
......
......@@ -27,14 +27,15 @@
*/
#include "config.h"
#include "GlyphMap.h"
#include "GlyphPageTreeNode.h"
#include "FontData.h"
#include <windows.h>
namespace WebCore
{
bool GlyphMap::fillPage(GlyphPage* page, UChar* buffer, unsigned bufferLength, const FontData* fontData)
bool GlyphPage::fill(UChar* buffer, unsigned bufferLength, const FontData* fontData)
{
HDC dc = GetDC((HWND)0);
SaveDC(dc);
......@@ -45,7 +46,7 @@ bool GlyphMap::fillPage(GlyphPage* page, UChar* buffer, unsigned bufferLength, c
WORD localGlyphBuffer[GlyphPage::size];
GetGlyphIndices(dc, buffer, bufferLength, localGlyphBuffer, 0);
for (unsigned i = 0; i < GlyphPage::size; i++)
page->setGlyphDataForIndex(i, localGlyphBuffer[i], fontData);
setGlyphDataForIndex(i, localGlyphBuffer[i], fontData);
RestoreDC(dc, -1);
ReleaseDC(0, dc);
return true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment