のねのBlog

パソコンの問題や、ソフトウェアの開発で起きた問題など書いていきます。よろしくお願いします^^。

IS_IN_BMP

400 already_AddRefed<gfxFont>
401 gfxFT2FontGroup::WhichSystemFontSupportsChar(PRUint32 aCh, PRInt32 aRunScript)
402 {
404    FontEntry *fe = static_cast<FontEntry*>
405        (gfxPlatformFontList::PlatformFontList()->
406            SystemFindFontForChar(aCh, aRunScript, &mStyle));
407    if (fe) {
408        nsRefPtr<gfxFT2Font> f = gfxFT2Font::GetOrMakeFont(fe, &mStyle);
409        nsRefPtr<gfxFont> font = f.get();
410        return font.forget();
411    }
420    return nsnull;
421 }
3982 already_AddRefed<gfxFont>
3983 gfxFontGroup::WhichSystemFontSupportsChar(PRUint32 aCh, PRInt32 aRunScript)
3984 {
3985    gfxFontEntry *fe =
3986        gfxPlatformFontList::PlatformFontList()->
3987            SystemFindFontForChar(aCh, aRunScript, &mStyle);
3988    if (fe) {
3989        // ignore bolder considerations in system fallback case...
3990        nsRefPtr<gfxFont> font = fe->FindOrMakeFont(&mStyle, false);
3991        return font.forget();
3992    }
3993
3994    return nsnull;
3995 }
441 gfxFontEntry*
442 gfxPlatformFontList::SystemFindFontForChar(const PRUint32 aCh,
443                                           PRInt32 aRunScript,
444                                           const gfxFontStyle* aStyle)
445 {
446    gfxFontEntry* fontEntry = nsnull;
447
448    // is codepoint with no matching font? return null immediately
449    if (mCodepointsWithNoFonts.test(aCh)) {
450        return nsnull;
451    }
452
453    // try to short-circuit font fallback for U+FFFD, used to represent
454    // encoding errors: just use a platform-specific fallback system
455    // font that is guaranteed (or at least highly likely) to be around,
456    // or a cached family from last time U+FFFD was seen. this helps
457    // speed up pages with lots of encoding errors, binary-as-text, etc.
458    if (aCh == 0xFFFD && mReplacementCharFallbackFamily.Length() > 0) {
459        bool needsBold;  // ignored in the system fallback case
460
461        fontEntry = FindFontForFamily(mReplacementCharFallbackFamily,
462                                      aStyle, needsBold);
463
464        if (fontEntry && fontEntry->TestCharacterMap(aCh))
465            return fontEntry;
466    }
467
468    TimeStamp start = TimeStamp::Now();
469
470    // search commonly available fonts
471    bool common = true;
472    fontEntry = CommonFontFallback(aCh, aRunScript, aStyle); <==============================
473
474    // if didn't find a font, do system-wide fallback (except for specials)
475    PRUint32 cmapCount = 0;
476    if (!fontEntry) {
477        common = false;
478        fontEntry = GlobalFontFallback(aCh, aRunScript, aStyle, cmapCount);
479    }
480    TimeDuration elapsed = TimeStamp::Now() - start;
481
482 #ifdef PR_LOGGING
483    PRLogModuleInfo *log = gfxPlatform::GetLog(eGfxLog_textrun);
484
485    if (NS_UNLIKELY(log)) {
486        PRUint32 charRange = gfxFontUtils::CharRangeBit(aCh);
487        PRUint32 unicodeRange = FindCharUnicodeRange(aCh);
488        PRInt32 script = mozilla::unicode::GetScriptCode(aCh);
489        PR_LOG(log, PR_LOG_WARNING,\
490               ("(textrun-systemfallback-%s) char: u+%6.6x "
491                 "char-range: %d unicode-range: %d script: %d match: [%s]"
492                " time: %dus cmaps: %d\n",
493                (common ? "common" : "global"), aCh,
494                 charRange, unicodeRange, script,
495                (fontEntry ? NS_ConvertUTF16toUTF8(fontEntry->Name()).get() :
496                    "<none>"),
497                PRInt32(elapsed.ToMicroseconds()),
498                cmapCount));
499    }
500 #endif
501
502    // no match? add to set of non-matching codepoints
503    if (!fontEntry) {
504         mCodepointsWithNoFonts.set(aCh);
505    } else if (aCh == 0xFFFD && fontEntry) {
506        mReplacementCharFallbackFamily = fontEntry->FamilyName();
507     }
508
509    // track system fallback time
510    static bool first = true;
511    PRInt32 intElapsed = PRInt32(first ? elapsed.ToMilliseconds() :
512                                         elapsed.ToMicroseconds());
513    Telemetry::Accumulate((first ? Telemetry::SYSTEM_FONT_FALLBACK_FIRST :
514                                   Telemetry::SYSTEM_FONT_FALLBACK),
515                          intElapsed);
516    first = false;
517
518    // track the script for which fallback occurred (incremented one make it
519    // 1-based)
520    Telemetry::Accumulate(Telemetry::SYSTEM_FONT_FALLBACK_SCRIPT, aRunScript + 1);
521
522    return fontEntry;
523 }
539 gfxFontEntry*
540 gfxPlatformFontList::CommonFontFallback(const PRUint32 aCh,
541                                        PRInt32 aRunScript,
542                                        const gfxFontStyle* aMatchStyle)
543 {
544    nsAutoTArray<const char*,NUM_FALLBACK_FONTS> defaultFallbacks;
545    PRUint32 i, numFallbacks;
546
547    gfxPlatform::GetPlatform()->GetCommonFallbackFonts(aCh, aRunScript,   <=============
548                                                       defaultFallbacks);
549    numFallbacks = defaultFallbacks.Length();
550    for (i = 0; i < numFallbacks; i++) {
551        nsAutoString familyName;
552        const char *fallbackFamily = defaultFallbacks[i];
553
554        familyName.AppendASCII(fallbackFamily);
555        gfxFontFamily *fallback =
556                gfxPlatformFontList::PlatformFontList()->FindFamily(familyName);
557        if (!fallback)
558            continue;
559
560        gfxFontEntry *fontEntry;
561        bool needsBold;  // ignored in the system fallback case
562
563        // use first font in list that supports a given character
564        fontEntry = fallback->FindFontForStyle(*aMatchStyle, needsBold);
565        if (fontEntry && fontEntry->TestCharacterMap(aCh)) {
566            return fontEntry;
567        }
568    }
569
570    return nsnull;
571 }
173 void
174 gfxAndroidPlatform::GetCommonFallbackFonts(const uint32_t aCh,
175                                           int32_t aRunScript,
176                                           nsTArray<const char*>& aFontList)
177 {
178    static const char kDroidSansJapanese[] = "Droid Sans Japanese";
179    static const char kMotoyaLMaru[] = "MotoyaLMaru";
180
181    if (IS_IN_BMP(aCh)) { <=========
182        // try language-specific "Droid Sans *" fonts for certain blocks,
183        // as most devices probably have these
184        uint8_t block = (aCh >> 8) & 0xff;
185        switch (block) {
186        case 0x05:
187            aFontList.AppendElement("Droid Sans Hebrew");
188            aFontList.AppendElement("Droid Sans Armenian");
189            break;
190        case 0x06:
191            aFontList.AppendElement("Droid Sans Arabic");
192            break;
193        case 0x09:
194            aFontList.AppendElement("Droid Sans Devanagari");
195            break;
196        case 0x0b:
197            aFontList.AppendElement("Droid Sans Tamil");
198            break;
199        case 0x0e:
200            aFontList.AppendElement("Droid Sans Thai");
201            break;
202        case 0x10: case 0x2d:
203            aFontList.AppendElement("Droid Sans Georgian");
204            break;
205        case 0x12: case 0x13:
206            aFontList.AppendElement("Droid Sans Ethiopic");
207            break;
208        case 0xf9: case 0xfa:
209            if (IsJapaneseLocale()) {
210                aFontList.AppendElement(kMotoyaLMaru);
211                aFontList.AppendElement(kDroidSansJapanese);
212            }
213            break;
214        default:
215            if (block >= 0x2e && block <= 0x9f && IsJapaneseLocale()) {
216                aFontList.AppendElement(kMotoyaLMaru);
217                aFontList.AppendElement(kDroidSansJapanese);
218            }
219            break;
220        }
221    }
222    // and try Droid Sans Fallback as a last resort
223    aFontList.AppendElement("Droid Sans Fallback");
224 }
81  * Some macros for converting PRUnichar (UTF-16) to and from Unicode scalar
82  * values.
83  *
84  * Note that UTF-16 represents all Unicode scalar values up to U+10FFFF by
85  * using "surrogate pairs". These consist of a high surrogate, i.e. a code
86  * point in the range U+D800 - U+DBFF, and a low surrogate, i.e. a code point
87  * in the range U+DC00 - U+DFFF, like this:
88  *
89  *  U+D800 U+DC00 =  U+10000
90  *  U+D800 U+DC01 =  U+10001
91  *  ...
92  *  U+DBFF U+DFFE = U+10FFFE
93  *  U+DBFF U+DFFF = U+10FFFF
94  *
95  * These surrogate code points U+D800 - U+DFFF are not themselves valid Unicode
96  * scalar values and are not well-formed UTF-16 except as high-surrogate /
97  * low-surrogate pairs.
98  */
99 
100 #define PLANE1_BASE          PRUint32(0x00010000) <=====================
101 // High surrogates are in the range 0xD800 -- OxDBFF
102 #define NS_IS_HIGH_SURROGATE(u) ((PRUint32(u) & 0xFFFFFC00) == 0xD800)
103 // Low surrogates are in the range 0xDC00 -- 0xDFFF
104 #define NS_IS_LOW_SURROGATE(u)  ((PRUint32(u) & 0xFFFFFC00) == 0xDC00)
105 // Faster than testing NS_IS_HIGH_SURROGATE || NS_IS_LOW_SURROGATE
106 #define IS_SURROGATE(u)      ((PRUint32(u) & 0xFFFFF800) == 0xD800)
107
108 // Everything else is not a surrogate: 0x000 -- 0xD7FF, 0xE000 -- 0xFFFF
109 
110 // N = (H - 0xD800) * 0x400 + 0x10000 + (L - 0xDC00)
111 // I wonder whether we could somehow assert that H is a high surrogate
112 // and L is a low surrogate
113 #define SURROGATE_TO_UCS4(h, l) (((PRUint32(h) & 0x03FF) << 10) + \
114                                 (PRUint32(l) & 0x03FF) + PLANE1_BASE)
115
116 // Extract surrogates from a UCS4 char
117 // Reference: the Unicode standard 4.0, section 3.9
118 // Since (c - 0x10000) >> 10 == (c >> 10) - 0x0080 and
119 // 0xD7C0 == 0xD800 - 0x0080,
120 // ((c - 0x10000) >> 10) + 0xD800 can be simplified to
121 #define H_SURROGATE(c) PRUnichar(PRUnichar(PRUint32(c) >> 10) + \
122                                 PRUnichar(0xD7C0))
123 // where it's to be noted that 0xD7C0 is not bitwise-OR'd
124 // but added.
125
126 // Since 0x10000 & 0x03FF == 0,
127 // (c - 0x10000) & 0x03FF == c & 0x03FF so that
128 // ((c - 0x10000) & 0x03FF) | 0xDC00 is equivalent to
129 #define L_SURROGATE(c) PRUnichar(PRUnichar(PRUint32(c) & PRUint32(0x03FF)) | \
130                                 PRUnichar(0xDC00))
131
132 #define IS_IN_BMP(ucs) (PRUint32(ucs) < PLANE1_BASE) <========================
133 #define UCS2_REPLACEMENT_CHAR PRUnichar(0xFFFD)
134
135 #define UCS_END PRUint32(0x00110000)
136 #define IS_VALID_CHAR(c) ((PRUint32(c) < UCS_END) && !IS_SURROGATE(c))
137 #define ENSURE_VALID_CHAR(c) (IS_VALID_CHAR(c) ? (c) : UCS2_REPLACEMENT_CHAR)