Reviewed by Darin.
authormjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Feb 2006 06:17:08 +0000 (06:17 +0000)
committermjs <mjs@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 28 Feb 2006 06:17:08 +0000 (06:17 +0000)
        - write a portable ICU version of TextEncoding::fromUnicode for use on win32

        * platform/StreamingTextDecoder.h:
        * platform/TextEncoding.cpp:
        (WebCore::TextEncoding::fromUnicode): added
        (WebCore::getConverter): helper
        (WebCore::cacheConverter): ditto
        (WebCore::effectiveEncoding): ditto
        * platform/mac/TextEncodingMac.cpp: Add comment
        * platform/win/TemporaryLinkStubs.cpp:
        (WebCore::TextEncoding::fromUnicode): remove

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

WebCore/ChangeLog
WebCore/platform/StreamingTextDecoder.h
WebCore/platform/TextEncoding.cpp
WebCore/platform/mac/TextEncodingMac.cpp
WebCore/platform/win/TemporaryLinkStubs.cpp

index 48d5caf..b583b24 100644 (file)
@@ -1,3 +1,19 @@
+2006-02-27  Maciej Stachowiak  <mjs@apple.com>
+
+        Reviewed by Darin.
+
+        - write a portable ICU version of TextEncoding::fromUnicode for use on win32
+
+        * platform/StreamingTextDecoder.h:
+        * platform/TextEncoding.cpp:
+        (WebCore::TextEncoding::fromUnicode): added
+        (WebCore::getConverter): helper
+        (WebCore::cacheConverter): ditto
+        (WebCore::effectiveEncoding): ditto
+        * platform/mac/TextEncodingMac.cpp: Add comment
+        * platform/win/TemporaryLinkStubs.cpp:
+        (WebCore::TextEncoding::fromUnicode): remove
+
 2006-02-27  Mitz Pettel  <opendarwin.org@mitzpettel.com>
 
         Test: fast/text/in-rendered-text-rtl.html
index 8755414..0b6d528 100644 (file)
@@ -62,7 +62,7 @@ namespace WebCore {
         unsigned char m_bufferedBytes[16]; // bigger than any single multi-byte character
         
         // ICU decoding.
-        UConverter *m_converterICU;
+        UConverterm_converterICU;
     };
     
 } // namespace WebCore
index 3d5d7fd..ac96a0f 100644 (file)
@@ -45,13 +45,6 @@ const char* TextEncoding::name() const
     return charsetNameFromTextEncodingID(m_encodingID);
 }
 
-inline TextEncodingID effectiveEncoding(TextEncodingID encoding)
-{
-    if (encoding == Latin1Encoding || encoding == ASCIIEncoding)
-        return WinLatin1Encoding;
-    return encoding;
-}
-
 QChar TextEncoding::backslashAsCurrencySymbol() const
 {
     if (m_flags & BackslashIsYen)
@@ -70,4 +63,110 @@ QString TextEncoding::toUnicode(const ByteArray &qba, int len) const
     return StreamingTextDecoder(*this).toUnicode(qba, len, true);
 }
 
+// We'd like to use ICU for this on OS X as well eventually, but we need to make sure
+// it covers all the encodings that we need
+#ifndef __APPLE__
+
+static UConverter* cachedConverter;
+static TextEncodingID cachedConverterEncoding = InvalidEncoding;
+
+static const int ConversionBufferSize = 16384;
+
+static inline UConverter* getConverter(TextEncodingID encoding, UErrorCode* status)
+{
+    if (cachedConverter && encoding == cachedConverterEncoding) {
+        UConverter* conv = cachedConverter;
+        cachedConverter = 0;
+        return conv;
+    }
+
+    const char* encodingName = charsetNameFromTextEncodingID(encoding);
+    UErrorCode err = U_ZERO_ERROR;
+    UConverter* conv = ucnv_open(encodingName, &err);
+    if (err == U_AMBIGUOUS_ALIAS_WARNING)
+        LOG_ERROR("ICU ambiguous alias warning for encoding: %s", encodingName);
+
+    if (!conv) {
+        LOG_ERROR("the ICU Converter won't convert to text encoding 0x%X, error %d", encoding, err);
+        *status = err;
+        return 0;
+    }
+
+    return conv;
+}
+
+static inline void cacheConverter(TextEncodingID id, UConverter* conv)
+{
+    if (conv) {
+        if (cachedConverter)
+            ucnv_close(cachedConverter);
+        cachedConverter = conv;
+        cachedConverterEncoding = id;
+    }
+}
+
+static inline TextEncodingID effectiveEncoding(TextEncodingID encoding)
+{
+    if (encoding == Latin1Encoding || encoding == ASCIIEncoding)
+        return WinLatin1Encoding;
+    return encoding;
+}
+
+QCString TextEncoding::fromUnicode(const QString &qcs, bool allowEntities) const
+{
+    TextEncodingID encoding = effectiveEncoding(m_encodingID);
+
+    if (encoding == WinLatin1Encoding && qcs.isAllLatin1())
+        return qcs.latin1();
+
+    if ((encoding == WinLatin1Encoding || encoding == UTF8Encoding || encoding == ASCIIEncoding) 
+        && qcs.isAllASCII())
+        return qcs.ascii();
+
+    // FIXME: We should see if there is "force ASCII range" mode in ICU;
+    // until then, we change the backslash into a yen sign.
+    // Encoding will change the yen sign back into a backslash.
+    QString copy = qcs;
+    copy.replace(QChar('\\'), backslashAsCurrencySymbol());
+
+    UErrorCode err = U_ZERO_ERROR;
+    UConverter* conv = getConverter(encoding, &err);
+    if (!conv && U_FAILURE(err))
+        return QCString();
+
+    ASSERT(conv);
+
+    // FIXME: when QString buffer is latin1, it would be nice to
+    // convert from that w/o having to allocate a unicode buffer
+
+    char buffer[ConversionBufferSize];
+    const UChar* source = reinterpret_cast<const UChar*>(copy.unicode());
+    const UChar* sourceLimit = source + copy.length();
+
+    QCString result(1); // for trailng zero
+
+    if (allowEntities)
+        ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_ESCAPE, UCNV_ESCAPE_XML_DEC, 0, 0, &err);
+    else {
+        ucnv_setSubstChars(conv, "?", 1, &err);
+        ucnv_setFromUCallBack(conv, UCNV_FROM_U_CALLBACK_SUBSTITUTE, 0, 0, 0, &err);
+    }
+
+    do {
+        char* target = buffer;
+        char* targetLimit = target + ConversionBufferSize;
+        err = U_ZERO_ERROR;
+        ucnv_fromUnicode(conv, &target, targetLimit, &source, sourceLimit, 0, true,  &err);
+        int count = target - buffer;
+        buffer[count] = 0;
+        result.append(buffer);
+    } while (err == U_BUFFER_OVERFLOW_ERROR);
+
+    cacheConverter(encoding, conv);
+
+    return result;
+}
+#endif
+
+
 } // namespace WebCore
index 3961ea9..44db1e1 100644 (file)
@@ -40,6 +40,8 @@ static inline TextEncodingID effectiveEncoding(TextEncodingID encoding)
     return encoding;
 }
 
+// We'd like to use ICU for this on OS X as well eventually, but we need to make sure
+// it covers all the encodings that we need
 QCString TextEncoding::fromUnicode(const QString &qcs, bool allowEntities) const
 {
     // FIXME: We should really use the same API in both directions.
index f3eb8e3..1d3fa99 100644 (file)
@@ -395,4 +395,3 @@ Widget* WebCore::FrameView::topLevelWidget() const { notImplemented(); return 0;
  class WebCore::Plugin *  WebCore::FrameWin::createPlugin(class KURL const &,class QStringList const &,class QStringList const &,class QString const &) { notImplemented(); return 0; }
  void  WebCore::FrameWin::handledOnloadEvents(void) { notImplemented(); }
 WebCore::String  WebCore::FrameWin::generateFrameName(void) { notImplemented(); return String(); }
-QCString WebCore::TextEncoding::fromUnicode(QString const&,bool) const { notImplemented(); return QCString(); }