bool GlyphPage::fill(unsigned offset, unsigned length, UChar* buffer, unsigned bufferLength, const SimpleFontData* fontData)
{
    if (SkUTF16_IsHighSurrogate(buffer[bufferLength-1])) {
        SkDebugf("%s last char is high-surrogate", __FUNCTION__);
        return false;
    }
    
    SkPaint paint;
    fontData->platformData().setupPaint(&paint);
    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);

    SkAutoSTMalloc <GlyphPage::size, uint16_t> glyphStorage(length);
    uint16_t* glyphs = glyphStorage.get();
    UChar *textBuffer = buffer;
    UChar vTextBuffer[bufferLength];

    if (fontData->platformData().orientation() == Vertical && !fontData->hasVerticalGlyphs()) {
        // Convert to vertical form if there is no vertical glyphs.
        for (unsigned i = 0; i < bufferLength; ++i) {
            vTextBuffer[i] = VerticalTextMap::getVerticalForm(buffer[i]);
            if (!vTextBuffer[i])
                vTextBuffer[i] = buffer[i];
        }
        textBuffer = vTextBuffer;
    }

    unsigned count = paint.textToGlyphs(textBuffer, bufferLength << 1, glyphs);
    if (count != length) {
        SkDebugf("%s count != length\n", __FUNCTION__);
        return false;
    }

    if (fontData->hasVerticalGlyphs()) {
        bool lookVariants = false;
        for (unsigned i = 0; i < bufferLength; ++i) {
            if (!Font::isCJKIdeograph(textBuffer[i])) {
                lookVariants = true;
                continue;
            }
        }
        if (lookVariants)
            substituteWithVerticalGlyphs(fontData->platformData(), glyphs, bufferLength);
    }

    unsigned allGlyphs = 0; // track if any of the glyphIDs are non-zero

    // search for emoji. If we knew for sure that buffer was a contiguous range
    // of chars, we could quick-reject the range to avoid this loop (usually)
    if (EmojiFont::IsAvailable()) {
        const UChar* curr = textBuffer;
        for (unsigned i = 0; i < length; i++) {
            SkUnichar uni = SkUTF16_NextUnichar(&curr);
            uint16_t glyphID = glyphs[i];
            // only sniff if the normal font failed to recognize it
            if (!glyphID)
                glyphID = EmojiFont::UnicharToGlyph(uni);
            setGlyphDataForIndex(offset + i, glyphID, fontData);
            allGlyphs |= glyphID;
        }
    } else {
        for (unsigned i = 0; i < length; i++) {
            uint16_t glyphID = glyphs[i];
            setGlyphDataForIndex(offset + i, glyphID, fontData);
            allGlyphs |= glyphID;
        }
    }
    return allGlyphs != 0;
}
static SkUnichar next_utf16(const void** chars) {
    return SkUTF16_NextUnichar((const uint16_t**)chars);
}
Beispiel #3
0
bool SkOSWindow::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_KEYDOWN: {
            SkKey key = winToskKey(wParam);
            if (kNONE_SkKey != key) {
                this->handleKey(key);
                return true;
            }
        } break;
        case WM_KEYUP: {
            SkKey key = winToskKey(wParam);
            if (kNONE_SkKey != key) {
                this->handleKeyUp(key);
                return true;
            }
        } break;
        case WM_UNICHAR:
            this->handleChar((SkUnichar) wParam);
            return true;
        case WM_CHAR: {
            const uint16_t* c = reinterpret_cast<uint16_t*>(&wParam);
            this->handleChar(SkUTF16_NextUnichar(&c));
            return true;
        } break;
        case WM_SIZE: {
            INT width = LOWORD(lParam);
            INT height = HIWORD(lParam);
            this->resize(width, height);
            break;
        }
        case WM_PAINT: {
            PAINTSTRUCT ps;
            HDC hdc = BeginPaint(hWnd, &ps);
            this->doPaint(hdc);
            EndPaint(hWnd, &ps);
            return true;
            } break;

        case WM_LBUTTONDOWN:
            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
                              Click::kDown_State, NULL, getModifiers(message));
            return true;

        case WM_MOUSEMOVE:
            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
                              Click::kMoved_State, NULL, getModifiers(message));
            return true;

        case WM_LBUTTONUP:
            this->handleClick(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam),
                              Click::kUp_State, NULL, getModifiers(message));
            return true;

        case WM_EVENT_CALLBACK:
            if (SkEvent::ProcessEvent()) {
                post_skwinevent(hWnd);
            }
            return true;
    }
    return false;
}
Beispiel #4
0
static int count_utf16(const char* text) {
    const uint16_t* prev = (uint16_t*)text;
    (void)SkUTF16_NextUnichar(&prev);
    return SkToInt((const char*)prev - text);
}
Beispiel #5
0
QVector<OsmAnd::TextRasterizer_P::LinePaint> OsmAnd::TextRasterizer_P::evaluatePaints(
    const QVector<QStringRef>& lineRefs,
    const Style& style) const
{
    // Prepare default paint
    SkPaint paint = _defaultPaint;
    paint.setTextSize(style.size);
    paint.setColor(style.color.toSkColor());

    // Transform text style to font style
    const SkFontStyle fontStyle(
        style.bold ? SkFontStyle::kBold_Weight : SkFontStyle::kNormal_Weight,
        SkFontStyle::kNormal_Width,
        style.italic ? SkFontStyle::kItalic_Slant : SkFontStyle::kUpright_Slant);

    const auto pText = lineRefs.first().string()->constData();

    QVector<LinePaint> linePaints;
    linePaints.reserve(lineRefs.count());
    for (const auto& lineRef : constOf(lineRefs))
    {
        LinePaint linePaint;
        linePaint.line = lineRef;

        TextPaint* pTextPaint = nullptr;
        const auto pLine = lineRef.constData();
        const auto pEnd = pLine + lineRef.size();
        auto pNextCharacter = pLine;
        while (pNextCharacter != pEnd)
        {
            const auto pCharacter = pNextCharacter;
            const auto position = pNextCharacter - pText;
            const auto characterUCS4 = SkUTF16_NextUnichar(reinterpret_cast<const uint16_t**>(&pNextCharacter));

            // First of all check previous font if it contains this character
            auto font = pTextPaint ? pTextPaint->paint.getTypeface() : nullptr;
            if (font)
            {
                SkPaint paint;
                paint.setTextEncoding(SkPaint::kUTF32_TextEncoding);
                paint.setTypeface(font);
                if (!paint.containsText(&characterUCS4, sizeof(uint32_t)))
                    font = nullptr;
#if OSMAND_LOG_CHARACTERS_FONT
                else
                {
                    SkString fontName;
                    font->getFamilyName(&fontName);

                    LogPrintf(LogSeverityLevel::Warning,
                              "UCS4 character 0x%08x (%u) has been found in '%s' font (reused)",
                              characterUCS4,
                              characterUCS4,
                              fontName.c_str());
                }
#endif // OSMAND_LOG_CHARACTERS_FONT
            }
            if (!font)
            {
                font = owner->fontFinder->findFontForCharacterUCS4(characterUCS4, fontStyle);

#if OSMAND_LOG_CHARACTERS_WITHOUT_FONT
                if (!font)
                {
                    LogPrintf(LogSeverityLevel::Warning,
                              "UCS4 character 0x%08x (%u) has not been found in any font",
                              characterUCS4,
                              characterUCS4);
                }
#endif // OSMAND_LOG_CHARACTERS_WITHOUT_FONT

#if OSMAND_LOG_CHARACTERS_FONT
                if (font)
                {
                    SkString fontName;
                    font->getFamilyName(&fontName);

                    LogPrintf(LogSeverityLevel::Warning,
                              "UCS4 character 0x%08x (%u) has been found in '%s' font",
                              characterUCS4,
                              characterUCS4,
                              fontName.c_str());
                }
#endif // OSMAND_LOG_CHARACTERS_FONT
            }

            if (pTextPaint == nullptr || pTextPaint->paint.getTypeface() != font)
            {
                linePaint.textPaints.push_back(qMove(TextPaint()));
                pTextPaint = &linePaint.textPaints.last();

                pTextPaint->text = QStringRef(lineRef.string(), position, 1);
                pTextPaint->paint = paint;
                pTextPaint->paint.setTypeface(font);

                SkPaint::FontMetrics metrics;
                pTextPaint->height = paint.getFontMetrics(&metrics);
                linePaint.maxFontHeight = qMax(linePaint.maxFontHeight, pTextPaint->height);
                linePaint.minFontHeight = qMin(linePaint.minFontHeight, pTextPaint->height);
                linePaint.maxFontLineSpacing = qMax(linePaint.maxFontLineSpacing, metrics.fLeading);
                linePaint.minFontLineSpacing = qMin(linePaint.minFontLineSpacing, metrics.fLeading);
                linePaint.maxFontTop = qMax(linePaint.maxFontTop, -metrics.fTop);
                linePaint.minFontTop = qMin(linePaint.minFontTop, -metrics.fTop);
                linePaint.maxFontBottom = qMax(linePaint.maxFontBottom, metrics.fBottom);
                linePaint.minFontBottom = qMin(linePaint.minFontBottom, metrics.fBottom);

                if (style.bold && (!font || (font && font->fontStyle().weight() <= SkFontStyle::kNormal_Weight)))
                    pTextPaint->paint.setFakeBoldText(true);
            }
            else
            {
                pTextPaint->text = QStringRef(lineRef.string(), pTextPaint->text.position(), pTextPaint->text.size() + 1);
            }
        }

        linePaints.push_back(qMove(linePaint));
    }

    return linePaints;
}