unsigned Character::expansionOpportunityCount(const LChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion, const TextJustify textJustify)
{
    unsigned count = 0;
    if (textJustify == TextJustifyDistribute) {
        isAfterExpansion = true;
        return length;
    }

    if (direction == LTR) {
        for (size_t i = 0; i < length; ++i) {
            if (treatAsSpace(characters[i])) {
                count++;
                isAfterExpansion = true;
            } else {
                isAfterExpansion = false;
            }
        }
    } else {
        for (size_t i = length; i > 0; --i) {
            if (treatAsSpace(characters[i - 1])) {
                count++;
                isAfterExpansion = true;
            } else {
                isAfterExpansion = false;
            }
        }
    }

    return count;
}
Beispiel #2
0
unsigned Font::expansionOpportunityCount(const UChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion)
{
    static bool expandAroundIdeographs = canExpandAroundIdeographsInComplexText();
    unsigned count = 0;
    if (direction == LTR) {
        for (size_t i = 0; i < length; ++i) {
            UChar32 character = characters[i];
            if (treatAsSpace(character)) {
                count++;
                isAfterExpansion = true;
                continue;
            }
            if (U16_IS_LEAD(character) && i + 1 < length && U16_IS_TRAIL(characters[i + 1])) {
                character = U16_GET_SUPPLEMENTARY(character, characters[i + 1]);
                i++;
            }
            if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
                if (!isAfterExpansion)
                    count++;
                count++;
                isAfterExpansion = true;
                continue;
            }
            isAfterExpansion = false;
        }
    } else {
        for (size_t i = length; i > 0; --i) {
            UChar32 character = characters[i - 1];
            if (treatAsSpace(character)) {
                count++;
                isAfterExpansion = true;
                continue;
            }
            if (U16_IS_TRAIL(character) && i > 1 && U16_IS_LEAD(characters[i - 2])) {
                character = U16_GET_SUPPLEMENTARY(characters[i - 2], character);
                i--;
            }
            if (expandAroundIdeographs && isCJKIdeographOrSymbol(character)) {
                if (!isAfterExpansion)
                    count++;
                count++;
                isAfterExpansion = true;
                continue;
            }
            isAfterExpansion = false;
        }
    }
    return count;
}
unsigned Character::expansionOpportunityCount(const UChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion, const TextJustify textJustify)
{
    unsigned count = 0;
    if (direction == LTR) {
        for (size_t i = 0; i < length; ++i) {
            UChar32 character = characters[i];
            if (treatAsSpace(character)) {
                count++;
                isAfterExpansion = true;
                continue;
            }
            if (U16_IS_LEAD(character) && i + 1 < length && U16_IS_TRAIL(characters[i + 1])) {
                character = U16_GET_SUPPLEMENTARY(character, characters[i + 1]);
                i++;
            }
            if (textJustify == TextJustify::TextJustifyAuto && isCJKIdeographOrSymbol(character)) {
                if (!isAfterExpansion)
                    count++;
                count++;
                isAfterExpansion = true;
                continue;
            }
            isAfterExpansion = false;
        }
    } else {
        for (size_t i = length; i > 0; --i) {
            UChar32 character = characters[i - 1];
            if (treatAsSpace(character)) {
                count++;
                isAfterExpansion = true;
                continue;
            }
            if (U16_IS_TRAIL(character) && i > 1 && U16_IS_LEAD(characters[i - 2])) {
                character = U16_GET_SUPPLEMENTARY(characters[i - 2], character);
                i--;
            }
            if (textJustify == TextJustify::TextJustifyAuto && isCJKIdeographOrSymbol(character)) {
                if (!isAfterExpansion)
                    count++;
                count++;
                isAfterExpansion = true;
                continue;
            }
            isAfterExpansion = false;
        }
    }
    return count;
}
void UniscribeHelper::adjustSpaceAdvances()
{
    if (m_spaceWidth == 0)
        return;

    int spaceWidthWithoutLetterSpacing = m_spaceWidth - m_letterSpacing;

    // This mostly matches what WebKit's UniscribeController::shapeAndPlaceItem.
    for (size_t run = 0; run < m_runs.size(); run++) {
        Shaping& shaping = m_shapes[run];

        for (int i = 0; i < shaping.charLength(); i++) {
            if (!treatAsSpace(m_input[m_runs[run].iCharPos + i]))
                continue;

            int glyphIndex = shaping.m_logs[i];
            int currentAdvance = shaping.m_advance[glyphIndex];

            // currentAdvance does not include additional letter-spacing, but
            // space_width does. Here we find out how off we are from the
            // correct width for the space not including letter-spacing, then
            // just subtract that diff.
            int diff = currentAdvance - spaceWidthWithoutLetterSpacing;
            // The shaping can consist of a run of text, so only subtract the
            // difference in the width of the glyph.
            shaping.m_advance[glyphIndex] -= diff;
            shaping.m_abc.abcB -= diff;
        }
    }
}
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
{
    if (!run.length())
        return 0;

    if (run.length() == 1 && treatAsSpace(run[0]))
        return QFontMetrics(font()).width(space) + run.padding();

    String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
    QString string = fromRawDataWithoutRef(sanitized);

    int w = QFontMetrics(font()).width(string);
    // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
    if (treatAsSpace(run[0]))
        w -= m_wordSpacing;

    return w + run.padding();
}
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*) const
{
    if (!run.length())
        return 0;
    const QString string = fixSpacing(qstring(run));
    int w = QFontMetrics(font()).width(string);
    // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
    if (treatAsSpace(run[0]))
        w -= m_wordSpacing;

    return w + run.padding();
}
Beispiel #7
0
unsigned Font::expansionOpportunityCount(const LChar* characters, size_t length, TextDirection direction, bool& isAfterExpansion)
{
    unsigned count = 0;
    if (direction == LTR) {
        for (size_t i = 0; i < length; ++i) {
            if (treatAsSpace(characters[i])) {
                count++;
                isAfterExpansion = true;
            } else
                isAfterExpansion = false;
        }
    } else {
        for (size_t i = length; i > 0; --i) {
            if (treatAsSpace(characters[i - 1])) {
                count++;
                isAfterExpansion = true;
            } else
                isAfterExpansion = false;
        }
    }
    return count;
}
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*) const
{
    if (!run.length())
        return 0;
    const QString string = fixSpacing(qstring(run));
    QTextLayout layout(string, font());
    QTextLine line = setupLayout(&layout, run);
    int w = int(line.naturalTextWidth());
    // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
    if (treatAsSpace(run[0]))
        w -= m_wordSpacing;

    return w + run.padding();
}
Beispiel #9
0
float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
    if (!primaryFont()->platformData().size())
        return 0;

    if (!run.length())
        return 0;

    String sanitized = Font::normalizeSpaces(run.characters(), run.length());
    QString string = fromRawDataWithoutRef(sanitized);

    int w = QFontMetrics(font()).width(string, -1, Qt::TextBypassShaping);

    // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
    if (treatAsSpace(run[0]))
        w -= m_wordSpacing;

    return w + run.expansion();
}
float Font::floatWidthForSimpleText(const TextRun& run, GlyphBuffer* glyphBuffer, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
    if (!run.length())
        return 0;

    String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
    QString string = fromRawDataWithoutRef(sanitized);

    int w = QFontMetrics(font()).width(string, -1, Qt::TextBypassShaping);

    // WebKit expects us to ignore word spacing on the first character (as opposed to what Qt does)
    if (treatAsSpace(run[0]))
        w -= m_wordSpacing;

    return w + run.padding();
#else
    Q_ASSERT(false);
    return 0.0f;
#endif
}
void UniscribeHelper::applySpacing()
{
    for (size_t run = 0; run < m_runs.size(); run++) {
        Shaping& shaping = m_shapes[run];
        bool isRtl = m_runs[run].a.fRTL;

        if (m_letterSpacing != 0) {
            // RTL text gets padded to the left of each character. We increment
            // the run's advance to make this happen. This will be balanced out
            // by NOT adding additional advance to the last glyph in the run.
            if (isRtl)
                shaping.m_prePadding += m_letterSpacing;

            // Go through all the glyphs in this run and increase the "advance"
            // to account for letter spacing. We adjust letter spacing only on
            // cluster boundaries.
            //
            // This works for most scripts, but may have problems with some
            // indic scripts. This behavior is better than Firefox or IE for
            // Hebrew.
            for (int i = 0; i < shaping.glyphLength(); i++) {
                if (shaping.m_visualAttributes[i].fClusterStart) {
                    // Ick, we need to assign the extra space so that the glyph
                    // comes first, then is followed by the space. This is
                    // opposite for RTL.
                    if (isRtl) {
                        if (i != shaping.glyphLength() - 1) {
                            // All but the last character just get the spacing
                            // applied to their advance. The last character
                            // doesn't get anything,
                            shaping.m_advance[i] += m_letterSpacing;
                            shaping.m_abc.abcB += m_letterSpacing;
                        }
                    } else {
                        // LTR case is easier, we just add to the advance.
                        shaping.m_advance[i] += m_letterSpacing;
                        shaping.m_abc.abcB += m_letterSpacing;
                    }
                }
            }
        }

        // Go through all the characters to find whitespace and insert the
        // extra wordspacing amount for the glyphs they correspond to.
        if (m_wordSpacing != 0) {
            for (int i = 0; i < shaping.charLength(); i++) {
                if (!treatAsSpace(m_input[m_runs[run].iCharPos + i]))
                    continue;

                // The char in question is a word separator...
                int glyphIndex = shaping.m_logs[i];

                // Spaces will not have a glyph in Uniscribe, it will just add
                // additional advance to the character to the left of the
                // space. The space's corresponding glyph will be the character
                // following it in reading order.
                if (isRtl) {
                    // In RTL, the glyph to the left of the space is the same
                    // as the first glyph of the following character, so we can
                    // just increment it.
                    shaping.m_advance[glyphIndex] += m_wordSpacing;
                    shaping.m_abc.abcB += m_wordSpacing;
                } else {
                    // LTR is actually more complex here, we apply it to the
                    // previous character if there is one, otherwise we have to
                    // apply it to the leading space of the run.
                    if (glyphIndex == 0)
                        shaping.m_prePadding += m_wordSpacing;
                    else {
                        shaping.m_advance[glyphIndex - 1] += m_wordSpacing;
                        shaping.m_abc.abcB += m_wordSpacing;
                    }
                }
            }
        }  // m_wordSpacing != 0

        // Loop for next run...
    }
}