Fix for 8954, separate the glyph map out into its own files and make it
authorhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 May 2006 21:29:03 +0000 (21:29 +0000)
committerhyatt <hyatt@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Wed, 17 May 2006 21:29:03 +0000 (21:29 +0000)
        cross-platform.

        Reviewed by darin

        * WebCore.xcodeproj/project.pbxproj:
        * platform/Font.cpp:
        (WebCore::WidthIterator::advance):
        * platform/FontData.h:
        (WebCore::FontData::glyphDataForCharacter):
        (WebCore::FontData::setGlyphDataForCharacter):
        * platform/GlyphMap.cpp: Added.
        (WebCore::GlyphMap::glyphDataForCharacter):
        (WebCore::GlyphMap::setGlyphDataForCharacter):
        (WebCore::GlyphMap::locatePage):
        * platform/GlyphMap.h: Added.
        (WebCore::GlyphMap::GlyphMap):
        (WebCore::GlyphMap::~GlyphMap):
        (WebCore::GlyphMap::GlyphPage::glyphDataForCharacter):
        (WebCore::GlyphMap::GlyphPage::setGlyphDataForCharacter):
        (WebCore::GlyphMap::GlyphPage::setGlyphDataForIndex):
        * platform/mac/FontData.mm:
        (-[NSFont WebCore]):
        (WidthMap::m_ATSUMirrors):
        (WidthMap::FontData::~FontData):
        (WidthMap::FontData::xHeight):
        (WidthMap::FontData::platformInit):
        (WidthMap::extendWidthMap):
        * platform/mac/GlyphMapMac.cpp: Added.
        (WebCore::GlyphMap::fillPage):
        * platform/mac/WebCoreSystemInterface.h:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@14450 268f45cc-cd09-0410-ab3c-d52691b4dbfc

WebCore/ChangeLog
WebCore/WebCore.xcodeproj/project.pbxproj
WebCore/platform/Font.cpp
WebCore/platform/FontData.h
WebCore/platform/GlyphMap.cpp [new file with mode: 0644]
WebCore/platform/GlyphMap.h [new file with mode: 0644]
WebCore/platform/mac/FontData.mm
WebCore/platform/mac/GlyphMapMac.cpp [new file with mode: 0644]
WebCore/platform/mac/WebCoreSystemInterface.h

index c4485ff5a54314ceeb821165b4c020dab54f5717..309ef60470712b9cbcd4c6dc52019b64a394cbbe 100644 (file)
@@ -1,3 +1,37 @@
+2006-05-17  David Hyatt  <hyatt@apple.com>
+
+        Fix for 8954, separate the glyph map out into its own files and make it
+        cross-platform.
+
+        Reviewed by darin
+
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/Font.cpp:
+        (WebCore::WidthIterator::advance):
+        * platform/FontData.h:
+        (WebCore::FontData::glyphDataForCharacter):
+        (WebCore::FontData::setGlyphDataForCharacter):
+        * platform/GlyphMap.cpp: Added.
+        (WebCore::GlyphMap::glyphDataForCharacter):
+        (WebCore::GlyphMap::setGlyphDataForCharacter):
+        (WebCore::GlyphMap::locatePage):
+        * platform/GlyphMap.h: Added.
+        (WebCore::GlyphMap::GlyphMap):
+        (WebCore::GlyphMap::~GlyphMap):
+        (WebCore::GlyphMap::GlyphPage::glyphDataForCharacter):
+        (WebCore::GlyphMap::GlyphPage::setGlyphDataForCharacter):
+        (WebCore::GlyphMap::GlyphPage::setGlyphDataForIndex):
+        * platform/mac/FontData.mm:
+        (-[NSFont WebCore]):
+        (WidthMap::m_ATSUMirrors):
+        (WidthMap::FontData::~FontData):
+        (WidthMap::FontData::xHeight):
+        (WidthMap::FontData::platformInit):
+        (WidthMap::extendWidthMap):
+        * platform/mac/GlyphMapMac.cpp: Added.
+        (WebCore::GlyphMap::fillPage):
+        * platform/mac/WebCoreSystemInterface.h:
+
 2006-05-17  Anders Carlsson  <acarlsson@apple.com>
 
         Reviewed by Maciej.
index 2438b069fee96dca27f4c8b88c553e6af60773ac..f84d7ccf82765df42902db26a08f796bc94a0dba 100644 (file)
                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 */; };
+               BC6DB4740A1A90FB00E5CD14 /* GlyphMap.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC6DB4730A1A90FB00E5CD14 /* GlyphMap.cpp */; };
+               BC6DB4D40A1AFEEF00E5CD14 /* GlyphMapMac.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC6DB4D30A1AFEEF00E5CD14 /* GlyphMapMac.cpp */; };
                BC73E25D0978682700EDFF8A /* FloatSize.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC73E25B0978682700EDFF8A /* FloatSize.cpp */; };
                BC73E25E0978682700EDFF8A /* FloatSize.h in Headers */ = {isa = PBXBuildFile; fileRef = BC73E25C0978682700EDFF8A /* FloatSize.h */; };
                BC73E2FF0978AF9C00EDFF8A /* IntPointArray.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BC73E2FC0978AF9C00EDFF8A /* IntPointArray.cpp */; };
                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>"; };
                BC73E25B0978682700EDFF8A /* FloatSize.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = FloatSize.cpp; sourceTree = "<group>"; };
                BC73E25C0978682700EDFF8A /* FloatSize.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = FloatSize.h; sourceTree = "<group>"; };
                BC73E2FC0978AF9C00EDFF8A /* IntPointArray.cpp */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.cpp.cpp; path = IntPointArray.cpp; sourceTree = "<group>"; };
                6582A14809999D6C00BEEB6D /* mac */ = {
                        isa = PBXGroup;
                        children = (
+                               BC6DB4D30A1AFEEF00E5CD14 /* GlyphMapMac.cpp */,
                                65A640F00533BB1F0085E777 /* BlockExceptions.h */,
                                65F80697054D9F86008BF776 /* BlockExceptions.mm */,
                                2D90660B0665D937006B6F1A /* ClipboardMac.h */,
                                BCC47E2409A3D6F100ADB771 /* FontFamily.cpp */,
                                BCC47E2509A3D6F100ADB771 /* FontFamily.h */,
                                BCC71A120A0FF94D0014EE6E /* GlyphBuffer.h */,
+                               BC6DB3680A1A7CB700E5CD14 /* GlyphMap.h */,
+                               BC6DB4730A1A90FB00E5CD14 /* GlyphMap.cpp */,
                                A823A75B09B6E53900B60641 /* GraphicsContext.cpp */,
                                935367E409AF77DD00D35CD6 /* GraphicsContext.h */,
                                938E685309F0BE04008A48EC /* GraphicsTypes.cpp */,
                                A80E73500A199C77007FB8C5 /* StyleBase.h in Headers */,
                                A80E73510A199C77007FB8C5 /* StyleList.h in Headers */,
                                A80E73520A199C77007FB8C5 /* CSSSelector.h in Headers */,
+                               BC6DB3690A1A7CB700E5CD14 /* GlyphMap.h in Headers */,
                                A80E7A180A19C3D6007FB8C5 /* JSHTMLMetaElement.h in Headers */,
                                A80E7B0C0A19D606007FB8C5 /* JSHTMLTitleElement.h in Headers */,
                                A80E7B0D0A19D606007FB8C5 /* JSHTMLLinkElement.h in Headers */,
                                A80E7B120A19D606007FB8C5 /* JSHTMLBaseElement.cpp in Sources */,
                                A80E7B130A19D606007FB8C5 /* JSHTMLTitleElement.cpp in Sources */,
                                A80E7B140A19D606007FB8C5 /* JSHTMLHeadElement.cpp in Sources */,
+                               BC6DB4740A1A90FB00E5CD14 /* GlyphMap.cpp in Sources */,
+                               BC6DB4D40A1AFEEF00E5CD14 /* GlyphMapMac.cpp in Sources */,
                                1A9EF4570A1B957D00332B63 /* JSCanvasRenderingContext2DCustom.cpp in Sources */,
                        );
                        runOnlyForDeploymentPostprocessing = 0;
index dd3a013f59d18b43d3e45b5317962fdb08de33ea..762dde2f6bbac6bcc52837f492274e58cb8573eb 100644 (file)
@@ -181,7 +181,9 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
         }
 
         // FIXME: Should go through fallback list eventually when we rework the glyph map.
-        Glyph glyph = fontData->glyphForCharacter(&fontData, c);
+        const GlyphData& glyphData = fontData->glyphDataForCharacter(c);
+        Glyph glyph = glyphData.glyph;
+        fontData = glyphData.fontData;
 
         // Try to find a substitute font if this font didn't have a glyph for a character in the
         // string. If one isn't found we end up drawing and measuring the 0 glyph, usually a box.
@@ -195,7 +197,7 @@ void WidthIterator::advance(int offset, GlyphBuffer* glyphBuffer)
                 if (localGlyphBuffer.size() == 1) {
                     assert(substituteFontData == localGlyphBuffer.fontDataAt(0));
                     glyph = localGlyphBuffer.glyphAt(0);
-                    fontData->updateGlyphMapEntry(c, glyph, substituteFontData);
+                    fontData->setGlyphDataForCharacter(c, glyph, substituteFontData);
                     fontData = substituteFontData;
                 }
             }
index 6a1eecdf7524091b96ea3e22c689eb8ec278f568..0b35575b5d611a9a25a5024fdfc4ac59c4743fb4 100644 (file)
@@ -28,7 +28,8 @@
 // FIXME: This is going to be cross-platform eventually, but for now we just compile on OS X.
 
 #include "FontPlatformData.h"
-#include "GlyphBuffer.h"
+#include "GlyphMap.h"
+#include <wtf/Noncopyable.h>
 
 // FIXME: Temporary.  Only needed to support API that's going to move.
 #include <unicode/umachine.h>
@@ -40,10 +41,9 @@ namespace WebCore
 
 class FontDescription;
 
-typedef struct WidthMap WidthMap;
-typedef struct GlyphMap GlyphMap;
+class WidthMap;
 
-class FontData
+class FontData : Noncopyable
 {
 public:
     FontData(const FontPlatformData& f);
@@ -61,21 +61,23 @@ public:
 
     float xHeight() const;
 
-    // FIXME: These are temporary API and will eventually move to the fallback list.
-    Glyph glyphForCharacter(const FontData **renderer, unsigned c) const;
-    void updateGlyphMapEntry(UChar c, Glyph glyph, const FontData *substituteRenderer) const;
-    // End temporary API
-
     float widthForGlyph(Glyph glyph) const;
     bool containsCharacters(const UChar* characters, int length) const;
 
     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); }
+
 #if __APPLE__
     NSFont* getNSFont() const { return m_font.font; }
 #endif
 
+private:
+    bool platformInit();
+
 public:
     int m_ascent;
     int m_descent;
@@ -85,7 +87,7 @@ public:
     void* m_styleGroup;
     
     FontPlatformData m_font;
-    mutable GlyphMap* m_characterToGlyphMap;
+    mutable GlyphMap m_characterToGlyphMap;
     mutable WidthMap* m_glyphToWidthMap;
 
     bool m_treatAsFixedPitch;
diff --git a/WebCore/platform/GlyphMap.cpp b/WebCore/platform/GlyphMap.cpp
new file mode 100644 (file)
index 0000000..e586aa5
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * 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 "FontData.h"
+
+#include <unicode/uchar.h>
+
+#define NO_BREAK_SPACE 0x00A0
+#define ZERO_WIDTH_SPACE 0x200B
+
+namespace WebCore
+{
+
+GlyphData GlyphMap::glyphDataForCharacter(UChar32 c, const FontData* fontData)
+{
+    unsigned pageNumber = (c / cGlyphPageSize);
+    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 / cGlyphPageSize);
+    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 * cGlyphPageSize;
+    unsigned short buffer[cGlyphPageSize * 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 = cGlyphPageSize;
+        for (i = 0; i < cGlyphPageSize; i++)
+            buffer[i] = start + i;
+
+        if (start == 0) {
+            // Control characters must not render at all.
+            for (i = 0; i < 0x20; ++i)
+                buffer[i] = ZERO_WIDTH_SPACE;
+            for (i = 0x7F; i < 0xA0; i++)
+                buffer[i] = ZERO_WIDTH_SPACE;
+
+            // \n, \t, and nonbreaking space must render as a space.
+            buffer[(int)'\n'] = ' ';
+            buffer[(int)'\t'] = ' ';
+            buffer[NO_BREAK_SPACE] = ' ';
+        }
+    } else {
+        bufferLength = cGlyphPageSize * 2;
+        for (i = 0; i < cGlyphPageSize; 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) {
+        if (!m_pages)
+            m_pages = new HashMap<int, GlyphPage*>;
+        m_pages->set(pageNumber, page);
+    }
+
+    return page;
+}
+
+}
diff --git a/WebCore/platform/GlyphMap.h b/WebCore/platform/GlyphMap.h
new file mode 100644 (file)
index 0000000..894f8d6
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * 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.
+ */
+
+#ifndef GLYPH_MAP_H
+#define GLYPH_MAP_H
+
+#include <unicode/umachine.h>
+#include "GlyphBuffer.h"
+#include <wtf/Noncopyable.h>
+#include <wtf/HashMap.h>
+
+namespace WebCore {
+
+// Covers Latin-1.
+const unsigned cGlyphPageSize = 256;
+
+class FontData;
+
+struct GlyphData
+{    
+    Glyph glyph;
+    const FontData* fontData;
+};
+
+class GlyphMap : Noncopyable
+{
+public:
+    GlyphMap() : m_filledPrimaryPage(false), m_pages(0) {}
+    ~GlyphMap() { deleteAllValues(*m_pages); delete m_pages; }
+
+    GlyphData glyphDataForCharacter(UChar32, const FontData*);
+    void setGlyphDataForCharacter(UChar32, Glyph, const FontData*);
+    
+private:
+    struct GlyphPage {
+        GlyphData m_glyphs[cGlyphPageSize];
+
+        const GlyphData& glyphDataForCharacter(UChar32 c) const { return m_glyphs[c % cGlyphPageSize]; }
+        void setGlyphDataForCharacter(UChar32 c, Glyph g, const FontData* f)
+        {
+            setGlyphDataForIndex(c % cGlyphPageSize, 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 Latin1.
+    HashMap<int, GlyphPage*>* m_pages;
+};
+
+}
+#endif
index 7ff2e6e23b473476d2f5a66de93394237bce33aa..22f30ef0d9732fa70e3906a5dbafe89bfc30998d 100644 (file)
 namespace WebCore
 {
 
-// FIXME: FATAL seems like a bad idea; lets stop using it.
-
 #define SMALLCAPS_FONTSIZE_MULTIPLIER 0.7f
-#define SYNTHETIC_OBLIQUE_ANGLE 14
-
-// Should be more than enough for normal usage.
-#define NUM_SUBSTITUTE_FONT_MAPS 10
-
 #define SPACE 0x0020
-#define NO_BREAK_SPACE 0x00A0
-#define ZERO_WIDTH_SPACE 0x200B
-#define POP_DIRECTIONAL_FORMATTING 0x202C
-#define LEFT_TO_RIGHT_OVERRIDE 0x202D
-#define RIGHT_TO_LEFT_OVERRIDE 0x202E
-
-// MAX_GLYPH_EXPANSION is the maximum numbers of glyphs that may be
-// use to represent a single Unicode code point.
-#define MAX_GLYPH_EXPANSION 4
-#define LOCAL_BUFFER_SIZE 2048
-
-// Covers Latin-1.
-#define INITIAL_BLOCK_SIZE 0x200
-
-// Get additional blocks of glyphs and widths in bigger chunks.
-// This will typically be for other character sets.
-#define INCREMENTAL_BLOCK_SIZE 0x400
-
 #define CONTEXT_DPI (72.0)
 #define SCALE_EM_TO_UNITS(X, U_PER_EM) (X * ((1.0 * CONTEXT_DPI) / (CONTEXT_DPI * U_PER_EM)))
 
-#define WKGlyphVectorSize (50 * 32)
-
 typedef float WebGlyphWidth;
 
 struct WidthMap {
@@ -102,27 +75,9 @@ struct WidthMap {
     WebGlyphWidth *widths;
 };
 
-typedef struct GlyphEntry {
-    Glyph glyph;
-    const FontData *renderer;
-} GlyphEntry;
-
-struct GlyphMap {
-    UChar startRange;
-    UChar endRange;
-    GlyphMap *next;
-    GlyphEntry *glyphs;
-};
-
 static WidthMap *extendWidthMap(const FontData *, ATSGlyphRef);
-static ATSGlyphRef extendGlyphMap(const FontData *, UChar32);
 
 static void freeWidthMap(WidthMap *);
-static void freeGlyphMap(GlyphMap *);
-
-static bool setUpFont(FontData *);
-
-static bool fillStyleWithAttributes(ATSUStyle style, NSFont *theFont);
 
 #if !ERROR_DISABLED
 static NSString *pathFromFont(NSFont *font);
@@ -164,7 +119,7 @@ static NSString *webFallbackFontFamily(void)
 }
 
 FontData::FontData(const FontPlatformData& f)
-:m_styleGroup(0), m_font(f), m_characterToGlyphMap(0), m_glyphToWidthMap(0), m_treatAsFixedPitch(false),
+:m_styleGroup(0), m_font(f), m_glyphToWidthMap(0), m_treatAsFixedPitch(false),
  m_smallCapsFontData(0), m_ATSUStyleInitialized(false), m_ATSUMirrors(false)
 {    
     m_font = f;
@@ -172,7 +127,7 @@ FontData::FontData(const FontPlatformData& f)
     m_syntheticBoldOffset = f.syntheticBold ? ceilf([f.font pointSize] / 24.0f) : 0.f;
     
     bool failedSetup = false;
-    if (!setUpFont(this)) {
+    if (!platformInit()) {
         // Ack! Something very bad happened, like a corrupt font.
         // Try looking for an alternate 'base' font for this renderer.
 
@@ -197,12 +152,12 @@ FontData::FontData(const FontPlatformData& f)
         if (!filePath)
             filePath = @"not known";
 #endif
-        if (!setUpFont(this)) {
+        if (!platformInit()) {
            if ([fallbackFontFamily isEqual:@"Times New Roman"]) {
                // OK, couldn't setup Times New Roman as an alternate to Times, fallback
                // on the system font.  If this fails we have no alternative left.
                m_font.font = [[NSFontManager sharedFontManager] convertFont:m_font.font toFamily:webFallbackFontFamily()];
-               if (!setUpFont(this)) {
+               if (!platformInit()) {
                    // We tried, Times, Times New Roman, and the system font. No joy. We have to give up.
                    LOG_ERROR("unable to initialize with font %@ at %@", initialFont, filePath);
                     failedSetup = true;
@@ -224,7 +179,7 @@ FontData::FontData(const FontPlatformData& f)
     if (failedSetup) {
         m_font.font = [NSFont systemFontOfSize:[m_font.font pointSize]];
         LOG_ERROR("failed to set up font, using system font %s", m_font.font);
-        setUpFont(this);
+        platformInit();
     }
     
     int iAscent;
@@ -261,7 +216,6 @@ FontData::~FontData()
         wkReleaseStyleGroup(m_styleGroup);
 
     freeWidthMap(m_glyphToWidthMap);
-    freeGlyphMap(m_characterToGlyphMap);
 
     if (m_ATSUStyleInitialized)
         ATSUDisposeStyle(m_ATSUStyle);
@@ -276,8 +230,7 @@ float FontData::xHeight() const
 {
     // 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.
-    const FontData *renderer = this;
-    NSGlyph xGlyph = glyphForCharacter(&renderer, 'x');
+    NSGlyph xGlyph = m_characterToGlyphMap.glyphDataForCharacter('x', this).glyph;
     if (xGlyph) {
         NSRect xBox = [m_font.font boundingRectForGlyph:xGlyph];
         // Use the maximum of either width or height because "x" is nearly square
@@ -332,50 +285,50 @@ bool FontData::containsCharacters(const UChar* characters, int length) const
     return result;
 }
 
-// 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.
-static bool computeWidthForSpace(FontData *renderer)
-{
-    renderer->m_spaceGlyph = extendGlyphMap(renderer, SPACE);
-    if (renderer->m_spaceGlyph == 0)
-        return false;
-
-    float width = renderer->widthForGlyph(renderer->m_spaceGlyph);
-
-    renderer->m_spaceWidth = width;
-
-    renderer->determinePitch();
-    renderer->m_adjustedSpaceWidth = renderer->m_treatAsFixedPitch ? ceilf(width) : roundf(width);
-    
-    return true;
-}
-
-static bool setUpFont(FontData *renderer)
+bool FontData::platformInit()
 {
     ATSUStyle fontStyle;
     if (ATSUCreateStyle(&fontStyle) != noErr)
         return false;
+    
+    ATSUFontID fontId = wkGetNSFontATSUFontId(m_font.font);
+    if (!fontId) {
+        ATSUDisposeStyle(fontStyle);
+        return false;
+    }
 
-    if (!fillStyleWithAttributes(fontStyle, renderer->m_font.font)) {
+    ATSUAttributeTag tag = kATSUFontTag;
+    ByteCount size = sizeof(ATSUFontID);
+    ATSUFontID *valueArray[1] = {&fontId};
+    OSStatus status = ATSUSetAttributes(fontStyle, 1, &tag, &size, (void* const*)valueArray);
+    if (status != noErr) {
         ATSUDisposeStyle(fontStyle);
         return false;
     }
 
-    if (wkGetATSStyleGroup(fontStyle, &renderer->m_styleGroup) != noErr) {
+    if (wkGetATSStyleGroup(fontStyle, &m_styleGroup) != noErr) {
         ATSUDisposeStyle(fontStyle);
         return false;
     }
 
     ATSUDisposeStyle(fontStyle);
 
-    if (!computeWidthForSpace(renderer)) {
-        freeGlyphMap(renderer->m_characterToGlyphMap);
-        renderer->m_characterToGlyphMap = 0;
-        wkReleaseStyleGroup(renderer->m_styleGroup);
-        renderer->m_styleGroup = 0;
+    // 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(SPACE, this).glyph;
+    if (m_spaceGlyph == 0) {
+        wkReleaseStyleGroup(m_styleGroup);
+        m_styleGroup = 0;
         return false;
     }
+
+    float width = widthForGlyph(m_spaceGlyph);
+
+    m_spaceWidth = width;
+
+    determinePitch();
+    m_adjustedSpaceWidth = m_treatAsFixedPitch ? ceilf(width) : roundf(width);
     
     return true;
 }
@@ -402,119 +355,6 @@ static NSString *pathFromFont(NSFont *font)
 
 #endif
 
-void FontData::updateGlyphMapEntry(UChar c, ATSGlyphRef glyph, const FontData *substituteRenderer) const
-{
-    GlyphMap *map;
-    for (map = m_characterToGlyphMap; map; map = map->next) {
-        UChar32 start = map->startRange;
-        if (c >= start && c <= map->endRange) {
-            int i = c - start;
-            map->glyphs[i].glyph = glyph;
-            // This renderer will leak.
-            // No problem though; we want it to stick around forever.
-            // Max theoretical retain counts applied here will be num_fonts_on_system * num_glyphs_in_font.
-            map->glyphs[i].renderer = substituteRenderer;
-            break;
-        }
-    }
-}
-
-static ATSGlyphRef extendGlyphMap(const FontData *renderer, UChar32 c)
-{
-    GlyphMap *map = new GlyphMap;
-    ATSLayoutRecord *glyphRecord;
-    char glyphVector[WKGlyphVectorSize];
-    UChar32 end, start;
-    unsigned blockSize;
-    
-    if (renderer->m_characterToGlyphMap == 0)
-        blockSize = INITIAL_BLOCK_SIZE;
-    else
-        blockSize = INCREMENTAL_BLOCK_SIZE;
-    start = (c / blockSize) * blockSize;
-    end = start + (blockSize - 1);
-
-    map->startRange = start;
-    map->endRange = end;
-    map->next = 0;
-    
-    unsigned i;
-    unsigned count = end - start + 1;
-    unsigned short buffer[INCREMENTAL_BLOCK_SIZE * 2 + 2];
-    unsigned bufferLength;
-
-    if (start < 0x10000) {
-        bufferLength = count;
-        for (i = 0; i < count; i++)
-            buffer[i] = i + start;
-
-        if (start == 0) {
-            // Control characters must not render at all.
-            for (i = 0; i < 0x20; ++i)
-                buffer[i] = ZERO_WIDTH_SPACE;
-            buffer[0x7F] = ZERO_WIDTH_SPACE;
-
-            // But \n, \t, and nonbreaking space must render as a space.
-            buffer[(int)'\n'] = ' ';
-            buffer[(int)'\t'] = ' ';
-            buffer[NO_BREAK_SPACE] = ' ';
-        }
-    } else {
-        bufferLength = count * 2;
-        for (i = 0; i < count; i++) {
-            int c = i + start;
-            buffer[i * 2] = U16_LEAD(c);
-            buffer[i * 2 + 1] = U16_TRAIL(c);
-        }
-    }
-
-    OSStatus status = wkInitializeGlyphVector(count, &glyphVector);
-    if (status != noErr) {
-        // This should never happen, perhaps indicates a bad font!  If it does the
-        // font substitution code will find an alternate font.
-        delete map;
-        return 0;
-    }
-
-    wkConvertCharToGlyphs(renderer->m_styleGroup, &buffer[0], bufferLength, &glyphVector);
-    unsigned numGlyphs = wkGetGlyphVectorNumGlyphs(&glyphVector);
-    if (numGlyphs != count) {
-        // This should never happen, perhaps indicates a bad font?
-        // If it does happen, the font substitution code will find an alternate font.
-        wkClearGlyphVector(&glyphVector);
-        delete map;
-        return 0;
-    }
-
-    map->glyphs = new GlyphEntry[count];
-    glyphRecord = (ATSLayoutRecord *)wkGetGlyphVectorFirstRecord(glyphVector);
-    for (i = 0; i < count; i++) {
-        map->glyphs[i].glyph = glyphRecord->glyphID;
-        map->glyphs[i].renderer = renderer;
-        glyphRecord = (ATSLayoutRecord *)((char *)glyphRecord + wkGetGlyphVectorRecordSize(glyphVector));
-    }
-    wkClearGlyphVector(&glyphVector);
-    
-    if (renderer->m_characterToGlyphMap == 0)
-        renderer->m_characterToGlyphMap = map;
-    else {
-        GlyphMap *lastMap = renderer->m_characterToGlyphMap;
-        while (lastMap->next != 0)
-            lastMap = lastMap->next;
-        lastMap->next = map;
-    }
-
-    ATSGlyphRef glyph = map->glyphs[c - start].glyph;
-
-    // Special case for characters 007F-00A0.
-    if (glyph == 0 && c >= 0x7F && c <= 0xA0) {
-        glyph = wkGetDefaultGlyphForChar(renderer->m_font.font, c);
-        map->glyphs[c - start].glyph = glyph;
-    }
-
-    return glyph;
-}
-
 static WidthMap *extendWidthMap(const FontData *renderer, ATSGlyphRef glyph)
 {
     WidthMap *map = new WidthMap;
@@ -524,19 +364,16 @@ static WidthMap *extendWidthMap(const FontData *renderer, ATSGlyphRef glyph)
     unsigned i, count;
     
     NSFont *f = renderer->m_font.font;
-    if (renderer->m_glyphToWidthMap == 0) {
-        if ([f numberOfGlyphs] < INITIAL_BLOCK_SIZE)
-            blockSize = [f numberOfGlyphs];
-         else
-            blockSize = INITIAL_BLOCK_SIZE;
-    } else {
-        blockSize = INCREMENTAL_BLOCK_SIZE;
-    }
-    if (blockSize == 0) {
+    if (renderer->m_glyphToWidthMap == 0 && [f numberOfGlyphs] < cGlyphPageSize)
+        blockSize = [f numberOfGlyphs];
+    else
+        blockSize = cGlyphPageSize;
+    
+    if (blockSize == 0)
         start = 0;
-    } else {
+    else
         start = (glyph / blockSize) * blockSize;
-    }
+
     end = ((unsigned)start) + blockSize; 
 
     map->startRange = start;
@@ -569,50 +406,6 @@ static void freeWidthMap(WidthMap *map)
     }
 }
 
-static void freeGlyphMap(GlyphMap *map)
-{
-    while (map) {
-        GlyphMap *next = map->next;
-        delete []map->glyphs;
-        delete map;
-        map = next;
-    }
-}
-
-Glyph FontData::glyphForCharacter(const FontData **renderer, unsigned c) const
-{
-    // this loop is hot, so it is written to avoid LSU stalls
-    GlyphMap *map;
-    GlyphMap *nextMap;
-    for (map = (*renderer)->m_characterToGlyphMap; map; map = nextMap) {
-        UChar start = map->startRange;
-        nextMap = map->next;
-        if (c >= start && c <= map->endRange) {
-            GlyphEntry *ge = &map->glyphs[c - start];
-            *renderer = ge->renderer;
-            return ge->glyph;
-        }
-    }
-
-    return extendGlyphMap(*renderer, c);
-}
-
-static bool fillStyleWithAttributes(ATSUStyle style, NSFont *theFont)
-{
-    if (!theFont)
-        return false;
-    ATSUFontID fontId = wkGetNSFontATSUFontId(theFont);
-    if (!fontId)
-        return false;
-    ATSUAttributeTag tag = kATSUFontTag;
-    ByteCount size = sizeof(ATSUFontID);
-    ATSUFontID *valueArray[1] = {&fontId};
-    OSStatus status = ATSUSetAttributes(style, 1, &tag, &size, (void* const*)valueArray);
-    if (status != noErr)
-        return false;
-    return true;
-}
-
 void FontData::determinePitch()
 {
     NSFont* f = m_font.font;
diff --git a/WebCore/platform/mac/GlyphMapMac.cpp b/WebCore/platform/mac/GlyphMapMac.cpp
new file mode 100644 (file)
index 0000000..ed26425
--- /dev/null
@@ -0,0 +1,68 @@
+/*
+ * 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 "FontData.h"
+#include "WebCoreSystemInterface.h"
+
+namespace WebCore
+{
+
+bool GlyphMap::fillPage(GlyphPage* page, 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)];
+    
+    OSStatus status = wkInitializeGlyphVector(cGlyphPageSize, &glyphVector);
+    if (status != noErr)
+        // This should never happen, perhaps indicates a bad font!  If it does the
+        // font substitution code will find an alternate font.
+        return false;
+
+    wkConvertCharToGlyphs(fontData->m_styleGroup, buffer, bufferLength, &glyphVector);
+
+    unsigned numGlyphs = wkGetGlyphVectorNumGlyphs(&glyphVector);
+    if (numGlyphs != cGlyphPageSize) {
+        // This should never happen, perhaps indicates a bad font?
+        // If it does happen, the font substitution code will find an alternate font.
+        wkClearGlyphVector(&glyphVector);
+        return false;
+    }
+
+    ATSLayoutRecord* glyphRecord = (ATSLayoutRecord*)wkGetGlyphVectorFirstRecord(glyphVector);
+    for (unsigned i = 0; i < cGlyphPageSize; i++) {
+        page->setGlyphDataForIndex(i, glyphRecord->glyphID, fontData);
+        glyphRecord = (ATSLayoutRecord *)((char *)glyphRecord + wkGetGlyphVectorRecordSize(glyphVector));
+    }
+    wkClearGlyphVector(&glyphVector);
+
+    return true;
+}
+
+}
\ No newline at end of file
index 63e23086c0806f4741dd324a68e6f9ec08726743..4dcdf417150833c9a9b3d26aa1961b037daef354 100644 (file)
 #define WebCoreSystemInterface_h
 
 typedef signed char BOOL;
+typedef struct _NSPoint NSPoint;
 typedef struct _NSRange NSRange;
+typedef struct _NSRect NSRect;
+
+#ifndef __OBJC__
+class NSImage;
+class NSString;
+#endif
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+#define GLYPH_VECTOR_SIZE (50 * 32)
+
 // In alphabetical order.
 
 extern BOOL (*wkCGContextGetShouldSmoothFonts)(CGContextRef);