のねのBlog

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

fill

 GlyphPage::size
     78     static const size_t size = 256; // Covers Latin-1 in a single page.
     65 const UChar noBreakSpace = 0x00A0;
     75 const UChar softHyphen = 0x00AD;
     76 const UChar space = 0x0020;

     61 const UChar leftToRightMark = 0x200E;
     66 const UChar objectReplacementCharacter = 0xFFFC;

     87 const UChar zeroWidthSpace = 0x200B;
     88 const UChar zeroWidthNoBreakSpace = 0xFEFF;
    106 /**
    107  * Get the lead surrogate (0xd800..0xdbff) for a
    108  * supplementary code point (0x10000..0x10ffff).
    109  * @param supplementary 32-bit code point (U+10000..U+10ffff)
    110  * @return lead surrogate (U+d800..U+dbff) for supplementary
    111  * @stable ICU 2.4
    112  */
    113 #define U16_LEAD(supplementary) (UChar)(((supplementary)>>10)+0xd7c0)
    114 
    115 /**
    116  * Get the trail surrogate (0xdc00..0xdfff) for a
    117  * supplementary code point (0x10000..0x10ffff).
    118  * @param supplementary 32-bit code point (U+10000..U+10ffff)
    119  * @return trail surrogate (U+dc00..U+dfff) for supplementary
    120  * @stable ICU 2.4
    121  */
    122 #define U16_TRAIL(supplementary) (UChar)(((supplementary)&0x3ff)|0xdc00)
    169 void GlyphPageTreeNode::initializePage(const FontData* fontData, unsigned pageNumber)
    170 {
    171     ASSERT(!m_page);
    172 
    173     // This function must not be called for the root of the tree, because that
    174     // level does not contain any glyphs.
    175     ASSERT(m_level > 0 && m_parent);
    176 
    177     // The parent's page will be 0 if we are level one or the parent's font data
    178     // did not contain any glyphs for that page.
    179     GlyphPage* parentPage = m_parent->page();
    180 
    181     // NULL FontData means we're being asked for the system fallback font.
    182     if (fontData) {
    183         if (m_level == 1) {
    184             // Children of the root hold pure pages. These will cover only one
    185             // font data's glyphs, and will have glyph index 0 if the font data does not
    186             // contain the glyph.
    187             unsigned start = pageNumber * GlyphPage::size; <= pageNumber * 256
                                                                   <= 0 * 256 = 0
                                                                   <= 1 * 256 = 256
                                                                   <= 4 * 256 = 1024
    188             UChar buffer[GlyphPage::size * 2 + 2];         <= 256*2+2
    189             unsigned bufferLength;
    190             unsigned i;
    191 
    192             // Fill in a buffer with the entire "page" of characters that we want to look up glyphs for.
    193             if (start < 0x10000) {
    194                 bufferLength = GlyphPage::size;       <= bufferLength = 256;
    195                 for (i = 0; i < GlyphPage::size; i++) <= startから順番に値をbufferへ書き込む
    196                     buffer[i] = start + i;
    197 
    198                 if (start == 0) {                                  <=0ページの場合
    199                     // Control characters must not render at all.
    200                     for (i = 0; i < 0x20; ++i)
    201                         buffer[i] = zeroWidthSpace;      <=制御コードはゼロスペース
    202                     for (i = 0x7F; i < 0xA0; i++)
    203                         buffer[i] = zeroWidthSpace;      <=7F〜A0もゼロスペース
    204                     buffer[softHyphen] = zeroWidthSpace; <=0xAD
    205 
    206                     // \n, \t, and nonbreaking space must render as a space.
    207                     buffer[(int)'\n'] = ' ';
    208                     buffer[(int)'\t'] = ' ';
    209                     buffer[noBreakSpace] = ' ';
    210                 } else if (start == (leftToRightMark & ~(GlyphPage::size - 1))) { <== (0x200E & 0xFFFFFF00) 下位1バイト落とす。
    211                     // LRM, RLM, LRE, RLE, ZWNJ, ZWJ, and PDF must not render at all.
    212                     buffer[leftToRightMark - start] = zeroWidthSpace;
    213                     buffer[rightToLeftMark - start] = zeroWidthSpace;
    214                     buffer[leftToRightEmbed - start] = zeroWidthSpace;
    215                     buffer[rightToLeftEmbed - start] = zeroWidthSpace;
    216                     buffer[leftToRightOverride - start] = zeroWidthSpace;
    217                     buffer[rightToLeftOverride - start] = zeroWidthSpace;
    218                     buffer[zeroWidthNonJoiner - start] = zeroWidthSpace;
    219                     buffer[zeroWidthJoiner - start] = zeroWidthSpace;
    220                     buffer[popDirectionalFormatting - start] = zeroWidthSpace;
    221                 } else if (start == (objectReplacementCharacter & ~(GlyphPage::size - 1))) {
    222                     // Object replacement character must not render at all.
    223                     buffer[objectReplacementCharacter - start] = zeroWidthSpace;
    224                 } else if (start == (zeroWidthNoBreakSpace & ~(GlyphPage::size - 1))) {
    225                     // ZWNBS/BOM must not render at all.
    226                     buffer[zeroWidthNoBreakSpace - start] = zeroWidthSpace;
    227                 }
    228             } else {
    229                 bufferLength = GlyphPage::size * 2;         <==0x10000以上
    230                 for (i = 0; i < GlyphPage::size; i++) {
    231                     int c = i + start;
    232                     buffer[i * 2] = U16_LEAD(c);
    233                     buffer[i * 2 + 1] = U16_TRAIL(c);
    234                 }
    235             }
    236 
    237             m_page = GlyphPage::create(this);
    238 
    239             // Now that we have a buffer full of characters, we want to get back an array
    240             // of glyph indices.  This part involves calling into the platform-specific
    241             // routine of our glyph map for actually filling in the page with the glyphs.
    242             // Success is not guaranteed. For example, Times fails to fill page 260, giving glyph data
    243             // for only 128 out of 256 characters.
    244             bool haveGlyphs;
    245             if (fontData->isSegmented()) {
    246                 haveGlyphs = false;
    247 
    248                 const SegmentedFontData* segmentedFontData = static_cast<const SegmentedFontData*>(fontData);
    249                 unsigned numRanges = segmentedFontData->numRanges();
    250                 bool zeroFilled = false;
    251                 RefPtr<GlyphPage> scratchPage;
    252                 GlyphPage* pageToFill = m_page.get();
    253                 for (unsigned i = 0; i < numRanges; i++) {
    254                     const FontDataRange& range = segmentedFontData->rangeAt(i);
    255                     // all this casting is to ensure all the parameters to min and max have the same type,
    256                     // to avoid ambiguous template parameter errors on Windows
    257                     int from = max(0, static_cast<int>(range.from()) - static_cast<int>(start));
    258                     int to = 1 + min(static_cast<int>(range.to()) - static_cast<int>(start), 
                                             static_cast<int>(GlyphPage::size) - 1);
    259                     if (from < static_cast<int>(GlyphPage::size) && to > 0) {
    260                         if (haveGlyphs && !scratchPage) {
    261                             scratchPage = GlyphPage::create(this);
    262                             pageToFill = scratchPage.get();
    263                         }
    264 
    265                         if (!zeroFilled) {
    266                             if (from > 0 || to < static_cast<int>(GlyphPage::size)) {
    267                                 for (unsigned i = 0; i < GlyphPage::size; i++)
    268                                     pageToFill->setGlyphDataForIndex(i, 0, 0);
    269                             }
    270                             zeroFilled = true;
    271                         }
    272                         haveGlyphs |= fill(pageToFill,
                                                   from,
                                                   to - from,
                                                   buffer + from * (start < 0x10000 ? 1 : 2),
                                                   (to - from) * (start < 0x10000 ? 1 : 2),
                                                   range.fontData());
                                                   <=====ここ

    273                         if (scratchPage) {
    274                             ASSERT(to <=  static_cast<int>(GlyphPage::size));
    275                             for (int j = from; j < to; j++) {
    276                                 if (!m_page->glyphAt(j) && pageToFill->glyphAt(j))
    277                                     m_page->setGlyphDataForIndex(j, pageToFill->glyphDataForIndex(j));
    278                             }
    279                         }
    280                     }
    281                 }
    282             } else
    283                 haveGlyphs = fill(m_page.get(),
                                          0,
                                          GlyphPage::size,
                                          buffer,
                                          bufferLength, 
                                          static_cast<const SimpleFontData*>(fontData));
                                          <=====ここ
    284 
    285             if (!haveGlyphs)
    286                 m_page = 0;
    287         } else if (parentPage && parentPage->owner() != m_parent) {
    288             // The page we're overriding may not be owned by our parent node.
    289             // This happens when our parent node provides no useful overrides
    290             // and just copies the pointer to an already-existing page (see
    291             // below).
    292             //
    293             // We want our override to be shared by all nodes that reference
    294             // that page to avoid duplication, and so standardize on having the
    295             // page's owner collect all the overrides.  Call getChild on the
    296             // page owner with the desired font data (this will populate
    297             // the page) and then reference it.
    298             m_page = parentPage->owner()->getChild(fontData, pageNumber)->page();
    299         } else {
    300             // Get the pure page for the fallback font (at level 1 with no
    301             // overrides). getRootChild will always create a page if one
    302             // doesn't exist, but the page doesn't necessarily have glyphs
    303             // (this pointer may be 0).
    304             GlyphPage* fallbackPage = getRootChild(fontData, pageNumber)->page();
    305             if (!parentPage) {
    306                 // When the parent has no glyphs for this page, we can easily
    307                 // override it just by supplying the glyphs from our font.
    308                 m_page = fallbackPage;
    309             } else if (!fallbackPage) {
    310                 // When our font has no glyphs for this page, we can just reference the
    311                 // parent page.
    312                 m_page = parentPage;
    313             } else {
    314                 // Combine the parent's glyphs and ours to form a new more complete page.
    315                 m_page = GlyphPage::create(this);
    316 
    317                 // Overlay the parent page on the fallback page. Check if the fallback font
    318                 // has added anything.
    319                 bool newGlyphs = false;
    320                 for (unsigned i = 0; i < GlyphPage::size; i++) {
    321                     if (parentPage->glyphAt(i))
    322                         m_page->setGlyphDataForIndex(i, parentPage->glyphDataForIndex(i));
    323                     else  if (fallbackPage->glyphAt(i)) {
    324                         m_page->setGlyphDataForIndex(i, fallbackPage->glyphDataForIndex(i));
    325                         newGlyphs = true;
    326                     } else
    327                         m_page->setGlyphDataForIndex(i, 0, 0);
    328                 }
    329 
    330                 if (!newGlyphs)
    331                     // We didn't override anything, so our override is just the parent page.
    332                     m_page = parentPage;
    333             }
    334         }
    335     } else {
    336         m_page = GlyphPage::create(this);
    337         // System fallback. Initialized with the parent's page here, as individual
    338         // entries may use different fonts depending on character. If the Font
    339         // ever finds it needs a glyph out of the system fallback page, it will
    340         // ask the system for the best font to use and fill that glyph in for us.
    341         if (parentPage)
    342             m_page->copyFrom(*parentPage);
    343         else
    344             m_page->clear();
    345     }
    346 }
 91 bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
     92 {
     93     if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
     94         SkDebugf("%s last char is high-surrogate", __FUNCTION__);
     95         return false;
     96     }
     97 
     98     SkPaint paint;
     99     fontData->platformData().setupPaint(&paint);
    100     paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);
    101 
    102     SkAutoSTMalloc <GlyphPage::size, uint16_t> glyphStorage(length);
    103     uint16_t* glyphs = glyphStorage.get();
    104     UChar *textBuffer = buffer;
    105     UChar vTextBuffer[bufferLength];
    106 
    107     if (fontData->platformData().orientation() == Vertical && !fontData->hasVerticalGlyphs()) {
    108         // Convert to vertical form if there is no vertical glyphs.
    109         convertToVerticalForms(buffer, vTextBuffer, bufferLength);
    110         textBuffer = vTextBuffer;
    111     }
    112 
    113     unsigned count = paint.textToGlyphs(textBuffer, bufferLength << 1, glyphs); <=====
    114     if (count != length) {
    115         SkDebugf("%s count != length\n", __FUNCTION__);
    116         return false;
    117     }
    118 
    119     if (fontData->hasVerticalGlyphs()) {
    120         bool lookVariants = false;
    121         for (unsigned i = 0; i < bufferLength; ++i) {
    122             if (!Font::isCJKIdeograph(textBuffer[i])) {
    123                 lookVariants = true;
    124                 break;
    125             }
    126         }
    127         if (lookVariants) {
    128             if (substituteWithVerticalGlyphs(fontData->platformData(), glyphs, bufferLength)) {
    129                 // Convert text to vertical forms if substituteWithVerticalGlyphs() fails to access vert tables.
    130                 convertToVerticalForms(buffer, vTextBuffer, bufferLength);
    131                 textBuffer = vTextBuffer;
    132 
    133                 unsigned count = paint.textToGlyphs(textBuffer, bufferLength << 1, glyphs);
    134                 if (count != length) {
    135                     SkDebugf("%s count != length\n", __FUNCTION__);
    136                     return false;
    137                 }
    138             }
    139         }
    140     }
    141 
    142     unsigned allGlyphs = 0; // track if any of the glyphIDs are non-zero
    143 
    144     // search for emoji. If we knew for sure that buffer was a contiguous range
    145     // of chars, we could quick-reject the range to avoid this loop (usually)
    146     if (EmojiFont::IsAvailable()) {
    147         const UChar* curr = textBuffer;
    148         for (unsigned i = 0; i < length; i++) {
    149             SkUnichar uni = SkUTF16_NextUnichar(&curr);
    150             uint16_t glyphID = glyphs[i];
    151             // only sniff if the normal font failed to recognize it
    152             if (!glyphID)
    153                 glyphID = EmojiFont::UnicharToGlyph(uni);
    154             setGlyphDataForIndex(offset + i, glyphID, fontData);
    155             allGlyphs |= glyphID;
    156         }
    157     } else {
    158         for (unsigned i = 0; i < length; i++) {
    159             uint16_t glyphID = glyphs[i];
    160             setGlyphDataForIndex(offset + i, glyphID, fontData);
    161             allGlyphs |= glyphID;
    162         }
    163     }
    164     return allGlyphs != 0;
    165 }
    485 int SkPaint::textToGlyphs(const void* textData, size_t byteLength,
    486                           uint16_t glyphs[]) const {
    487     if (byteLength == 0) {
    488         return 0;
    489     }
    490 
    491     SkASSERT(textData != NULL);
    492 
    493     if (NULL == glyphs) {
    494         switch (this->getTextEncoding()) {
    495         case kUTF8_TextEncoding:
    496             return SkUTF8_CountUnichars((const char*)textData, byteLength);
    497         case kUTF16_TextEncoding:
    498             return SkUTF16_CountUnichars((const uint16_t*)textData,
    499                                          byteLength >> 1);
    500         case kGlyphID_TextEncoding:
    501             return byteLength >> 1;
    502         default:
    503             SkDEBUGFAIL("unknown text encoding");
    504         }
    505         return 0;
    506     }
    507 
    508     // if we get here, we have a valid glyphs[] array, so time to fill it in
    509 
    510     // handle this encoding before the setup for the glyphcache
    511     if (this->getTextEncoding() == kGlyphID_TextEncoding) {
    512         // we want to ignore the low bit of byteLength
    513         memcpy(glyphs, textData, byteLength >> 1 << 1);
    514         return byteLength >> 1;
    515     }
    516 
    517     SkAutoGlyphCache autoCache(*this, NULL);
    518     SkGlyphCache*    cache = autoCache.getCache();
    519 
    520     const char* text = (const char*)textData;
    521     const char* stop = text + byteLength;
    522     uint16_t*   gptr = glyphs;
    523 
    524     switch (this->getTextEncoding()) {
    525         case SkPaint::kUTF8_TextEncoding:
    526             while (text < stop) {
    527                 *gptr++ = cache->unicharToGlyph(SkUTF8_NextUnichar(&text));
    528             }
    529             break;
    530         case SkPaint::kUTF16_TextEncoding: {
    531             const uint16_t* text16 = (const uint16_t*)text;
    532             const uint16_t* stop16 = (const uint16_t*)stop;
    533             while (text16 < stop16) {
    534                 *gptr++ = cache->unicharToGlyph(SkUTF16_NextUnichar(&text16));
    535             }
    536             break;
    537         }
    538         default:
    539             SkDEBUGFAIL("unknown text encoding");
    540     }
    541     return gptr - glyphs;
    542 }

unicharToGlyphへ - のねの日記