From fe6c972cff80e4a899b0351fa39af666533f7d76 Mon Sep 17 00:00:00 2001 From: "masayuki%d-toybox.com" Date: Wed, 14 Dec 2005 14:51:10 +0000 Subject: [PATCH] Bug 311378 freeze/hang in several seconds when a character which does not exist in fonts is rendered. patch by Masatoshi Kimura (emk) r=timeless, sr=rbs --- gfx/src/windows/nsFontMetricsWin.cpp | 64 +++++++++++++- gfx/src/windows/nsUnicodeRange.cpp | 30 +++++-- gfx/src/windows/nsUnicodeRange.h | 121 --------------------------- 3 files changed, 88 insertions(+), 127 deletions(-) diff --git a/gfx/src/windows/nsFontMetricsWin.cpp b/gfx/src/windows/nsFontMetricsWin.cpp index 7d2b98bf884..b4f5c6ba904 100644 --- a/gfx/src/windows/nsFontMetricsWin.cpp +++ b/gfx/src/windows/nsFontMetricsWin.cpp @@ -1307,7 +1307,7 @@ static PRUint8 gBitToUnicodeRange[] = /* 66 */ kRangeArabic, // fe50 - fe6f Small Form Variants /* 67 */ kRangeArabic, // fe70 - fefe Arabic Presen. FormsB /* 68 */ kRangeSetCJK, // ff00 - ffef Half/Fullwidth Forms - /* 69 */ kRangeSetCJK, // fff0 - fffd Specials + /* 69 */ kRangeSpecials, // fff0 - fffd Specials /* 70 */ kRangeTibetan, // 0f00 - 0fcf Tibetan /* 71 */ kRangeSyriac, // 0700 - 074f Syriac /* 72 */ kRangeThaana, // 0780 - 07bf Thaana @@ -2730,6 +2730,9 @@ nsFontMetricsWin::SameAsPreviousMap(int aIndex) if (tmp->flags & NS_GLOBALFONT_SKIP) { continue; } + if (!tmp->ccmap) { + continue; + } if (tmp->ccmap == font->ccmap) { font->flags |= NS_GLOBALFONT_SKIP; return 1; @@ -2744,6 +2747,24 @@ nsFontMetricsWin::SameAsPreviousMap(int aIndex) return 0; } +#ifndef WINCE +static +void BitFromUnicodeRange(PRUint32 range, DWORD* usb) +{ + for (int i = 0, dword = 0; dword < 3; ++dword) { + for (int bit = 0; bit < sizeof(DWORD) * 8; ++bit, ++i) { + if (range == gBitToUnicodeRange[i]) { + usb[dword] |= 1 << bit; + } + } + } +} +#endif + +#ifdef DEBUG_emk +static LARGE_INTEGER freq, prev; +#endif + nsFontWin* nsFontMetricsWin::FindGlobalFont(HDC aDC, PRUint32 c) { @@ -2753,6 +2774,12 @@ nsFontMetricsWin::FindGlobalFont(HDC aDC, PRUint32 c) return nsnull; } } +#ifndef WINCE + PRUint32 range = (c <= 0xFFFF) ? FindCharUnicodeRange(c) : kRangeSurrogate; + DWORD usb[4]; + memset(usb, 0, sizeof(usb)); + BitFromUnicodeRange(range, usb); +#endif int count = gGlobalFonts->Count(); for (int i = 0; i < count; ++i) { nsGlobalFont* font = (nsGlobalFont*)gGlobalFonts->ElementAt(i); @@ -2760,6 +2787,15 @@ nsFontMetricsWin::FindGlobalFont(HDC aDC, PRUint32 c) continue; } if (!font->ccmap) { +#ifndef WINCE + // bail out if Unicode range indicates the font have no glyph + if (font->flags & NS_GLOBALFONT_TRUETYPE && + !(font->signature.fsUsb[0] & usb[0]) && + !(font->signature.fsUsb[1] & usb[1]) && + !(font->signature.fsUsb[2] & usb[2])) { + continue; + } +#endif // don't adjust here, we just want to quickly get the CMAP. Adjusting // is meant to only happen when loading the final font in LoadFont() HFONT hfont = ::CreateFontIndirect(&font->logFont); @@ -2775,14 +2811,28 @@ nsFontMetricsWin::FindGlobalFont(HDC aDC, PRUint32 c) font->flags |= NS_GLOBALFONT_SKIP; continue; } +#ifdef DEBUG_emk + LARGE_INTEGER now; + QueryPerformanceCounter(&now); + printf("CCMAP loaded: %g sec, %s [%08X][%08X][%08X]\n", (now.QuadPart - prev.QuadPart) / (double)freq.QuadPart, + font->logFont.lfFaceName, font->signature.fsUsb[0], font->signature.fsUsb[1], font->signature.fsUsb[2]); + prev = now; +#endif if (SameAsPreviousMap(i)) { continue; } } if (CCMAP_HAS_CHAR_EXT(font->ccmap, c)) { +#ifdef DEBUG_emk + printf("font found:[%s]\n", font->logFont.lfFaceName); + printf("U+%04X (%d)[%08X][%08X][%08X]\n", c, range, usb[0], usb[1], usb[2]); +#endif return LoadGlobalFont(aDC, font); } } +#ifdef DEBUG_emk + printf("U+%04X (%d)[%08X][%08X][%08X]\n", c, range, usb[0], usb[1], usb[2]); +#endif return nsnull; } @@ -3555,6 +3605,11 @@ nsFontMetricsWin::FindPrefFont(HDC aDC, PRUint32 aChar) nsFontWin* nsFontMetricsWin::FindFont(HDC aDC, PRUint32 aChar) { +#ifdef DEBUG_emk + LARGE_INTEGER start, end; + QueryPerformanceFrequency(&freq); + QueryPerformanceCounter(&start); +#endif // the first font should be for invisible ignorable characters if (mLoadedFonts.Count() < 1) mLoadedFonts.AppendElement(gFontForIgnorable); @@ -3569,8 +3624,15 @@ nsFontMetricsWin::FindFont(HDC aDC, PRUint32 aChar) if (!font) { font = FindPrefFont(aDC, aChar); if (!font) { +#ifdef DEBUG_emk + QueryPerformanceCounter(&prev); +#endif font = FindGlobalFont(aDC, aChar); if (!font) { +#ifdef DEBUG_emk + QueryPerformanceCounter(&end); + printf("%g sec.\n", (end.QuadPart - start.QuadPart) / (double)freq.QuadPart); +#endif font = FindSubstituteFont(aDC, aChar); } } diff --git a/gfx/src/windows/nsUnicodeRange.cpp b/gfx/src/windows/nsUnicodeRange.cpp index 09341c2269c..9781e8a78cf 100644 --- a/gfx/src/windows/nsUnicodeRange.cpp +++ b/gfx/src/windows/nsUnicodeRange.cpp @@ -206,7 +206,7 @@ const char *gUnicodeRangeToLangGroupTable[] = -#define NUM_OF_SUBTABLES 7 +#define NUM_OF_SUBTABLES 8 #define SUBTABLE_SIZE 16 static PRUint8 gUnicodeSubrangeTable[NUM_OF_SUBTABLES][SUBTABLE_SIZE] = @@ -339,8 +339,26 @@ static PRUint8 gUnicodeSubrangeTable[NUM_OF_SUBTABLES][SUBTABLE_SIZE] = // CJK compatibility forms, // small form variants - kRangeSetCJK, //uffxx, halfwidth and fullwidth forms, includes Special - } + kRangeTableBase+7, //uffxx, halfwidth and fullwidth forms, includes Special + }, + { //table for 0xff00 - 0xffff + kRangeSetCJK, //uff0x, fullwidth latin + kRangeSetCJK, //uff1x, fullwidth latin + kRangeSetCJK, //uff2x, fullwidth latin + kRangeSetCJK, //uff3x, fullwidth latin + kRangeSetCJK, //uff4x, fullwidth latin + kRangeSetCJK, //uff5x, fullwidth latin + kRangeSetCJK, //uff6x, halfwidth katakana + kRangeSetCJK, //uff7x, halfwidth katakana + kRangeSetCJK, //uff8x, halfwidth katakana + kRangeSetCJK, //uff9x, halfwidth katakana + kRangeSetCJK, //uffax, halfwidth hangul jamo + kRangeSetCJK, //uffbx, halfwidth hangul jamo + kRangeSetCJK, //uffcx, halfwidth hangul jamo + kRangeSetCJK, //uffdx, halfwidth hangul jamo + kRangeSetCJK, //uffex, fullwidth symbols + kRangeSpecials, //ufffx, Specials + }, }; // Most scripts between U+0700 and U+16FF are assigned a chunk of 128 (0x80) @@ -407,9 +425,11 @@ PRUint32 FindCharUnicodeRange(PRUnichar ch) // otherwise, we have one more table to look at range = gUnicodeSubrangeTable[range - kRangeTableBase][(ch & 0x0f00) >> 8]; + if (range < kRangeTableBase) + return range; if (range < kRangeTertiaryTable) - return range; + return gUnicodeSubrangeTable[range - kRangeTableBase][(ch & 0x00f0) >> 4]; // Yet another table to look at : U+0700 - U+16FF : 128 code point blocks - return gUnicodeTertiaryRangeTable[(ch - 0x0700) >> 7]; + return gUnicodeTertiaryRangeTable[(ch - 0x0700) >> 7]; } diff --git a/gfx/src/windows/nsUnicodeRange.h b/gfx/src/windows/nsUnicodeRange.h index eda3014b9e7..e69de29bb2d 100644 --- a/gfx/src/windows/nsUnicodeRange.h +++ b/gfx/src/windows/nsUnicodeRange.h @@ -1,121 +0,0 @@ -/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ -/* ***** BEGIN LICENSE BLOCK ***** - * Version: MPL 1.1/GPL 2.0/LGPL 2.1 - * - * The contents of this file are subject to the Mozilla Public License Version - * 1.1 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/ - * - * Software distributed under the License is distributed on an "AS IS" basis, - * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License - * for the specific language governing rights and limitations under the - * License. - * - * The Original Code is mozilla.org code. - * - * The Initial Developer of the Original Code is - * Netscape Communications Corporation. - * Portions created by the Initial Developer are Copyright (C) 1998 - * the Initial Developer. All Rights Reserved. - * - * Contributor(s): - * - * Alternatively, the contents of this file may be used under the terms of - * either of the GNU General Public License Version 2 or later (the "GPL"), - * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), - * in which case the provisions of the GPL or the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of either the GPL or the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the GPL or the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of any one of the MPL, the GPL or the LGPL. - * - * ***** END LICENSE BLOCK ***** */ - -#include "nscore.h" - -// The following constants define unicode subranges -// values below kRangeNum must be continuous so that we can map to -// lang group directly. -// all ranges we care about should be defined under 32, that allows -// us to store range using bits of a PRUint32 - -// frequently used range definitions -const PRUint8 kRangeCyrillic = 0; -const PRUint8 kRangeGreek = 1; -const PRUint8 kRangeTurkish = 2; -const PRUint8 kRangeHebrew = 3; -const PRUint8 kRangeArabic = 4; -const PRUint8 kRangeBaltic = 5; -const PRUint8 kRangeThai = 6; -const PRUint8 kRangeKorean = 7; -const PRUint8 kRangeJapanese = 8; -const PRUint8 kRangeSChinese = 9; -const PRUint8 kRangeTChinese = 10; -const PRUint8 kRangeDevanagari = 11; -const PRUint8 kRangeTamil = 12; -const PRUint8 kRangeArmenian = 13; -const PRUint8 kRangeBengali = 14; -const PRUint8 kRangeCanadian = 15; -const PRUint8 kRangeEthiopic = 16; -const PRUint8 kRangeGeorgian = 17; -const PRUint8 kRangeGujarati = 18; -const PRUint8 kRangeGurmukhi = 19; -const PRUint8 kRangeKhmer = 20; -const PRUint8 kRangeMalayalam = 21; - -const PRUint8 kRangeSpecificItemNum = 22; - -//range/rangeSet grow to this place 22-29 - -const PRUint8 kRangeSetStart = 30; // range set definition starts from here -const PRUint8 kRangeSetLatin = 30; -const PRUint8 kRangeSetCJK = 31; -const PRUint8 kRangeSetEnd = 31; // range set definition ends here - -// less frequently used range definition -const PRUint8 kRangeSurrogate = 32; -const PRUint8 kRangePrivate = 33; -const PRUint8 kRangeMisc = 34; -const PRUint8 kRangeUnassigned = 35; -const PRUint8 kRangeSyriac = 36; -const PRUint8 kRangeThaana = 37; -const PRUint8 kRangeOriya = 38; -const PRUint8 kRangeTelugu = 39; -const PRUint8 kRangeKannada = 40; -const PRUint8 kRangeSinhala = 41; -const PRUint8 kRangeLao = 42; -const PRUint8 kRangeTibetan = 43; -const PRUint8 kRangeMyanmar = 44; -const PRUint8 kRangeCherokee = 45; -const PRUint8 kRangeOghamRunic = 46; -const PRUint8 kRangeMongolian = 47; -const PRUint8 kRangeMathOperators = 48; -const PRUint8 kRangeMiscTechnical = 49; -const PRUint8 kRangeControlOpticalEnclose = 50; -const PRUint8 kRangeBoxBlockGeometrics = 51; -const PRUint8 kRangeMiscSymbols = 52; -const PRUint8 kRangeDingbats = 53; -const PRUint8 kRangeBraillePattern = 54; -const PRUint8 kRangeYi = 55; -const PRUint8 kRangeCombiningDiacriticalMarks = 56; - -const PRUint8 kRangeTableBase = 128; //values over 127 are reserved for internal use only -const PRUint8 kRangeTertiaryTable = 145; // leave room for 16 subtable - // indices (kRangeTableBase + 1 .. - // kRangeTableBase + 16) - - - -extern PRUint32 FindCharUnicodeRange(PRUnichar ch); -extern const char* gUnicodeRangeToLangGroupTable[]; - -inline const char* LangGroupFromUnicodeRange(PRUint8 unicodeRange) -{ - if (kRangeSpecificItemNum > unicodeRange) - return gUnicodeRangeToLangGroupTable[unicodeRange]; - return nsnull; -}