예제 #1
0
static unsigned rightTruncateToBuffer(const String& string, unsigned length, unsigned keepCount, UChar* buffer)
{
    ASSERT(keepCount < length);
    ASSERT(keepCount < STRING_BUFFER_SIZE);
    
    TextBreakIterator* it = characterBreakIterator(string.characters(), length);
    unsigned keepLength = textBreakAtOrPreceding(it, keepCount);
    unsigned truncatedLength = keepLength + 1;
    
    memcpy(buffer, string.characters(), sizeof(UChar) * keepLength);
    buffer[keepLength] = horizontalEllipsis;
    
    return truncatedLength;
}
예제 #2
0
static unsigned centerTruncateToBuffer(const String& string, unsigned length, unsigned keepCount, UChar* buffer)
{
    ASSERT(keepCount < length);
    ASSERT(keepCount < STRING_BUFFER_SIZE);
    
    unsigned omitStart = (keepCount + 1) / 2;
    TextBreakIterator* it = characterBreakIterator(string.characters(), length);
    unsigned omitEnd = boundedTextBreakFollowing(it, omitStart + (length - keepCount) - 1, length);
    omitStart = textBreakAtOrPreceding(it, omitStart);
    
    unsigned truncatedLength = omitStart + 1 + (length - omitEnd);
    ASSERT(truncatedLength <= length);

    memcpy(buffer, string.characters(), sizeof(UChar) * omitStart);
    buffer[omitStart] = horizontalEllipsis;
    memcpy(&buffer[omitStart + 1], &string.characters()[omitEnd], sizeof(UChar) * (length - omitEnd));
    
    return truncatedLength;
}
예제 #3
0
파일: Text.cpp 프로젝트: Chingliu/EAWebkit
PassRefPtr<Text> Text::createWithLengthLimit(Document* doc, const String& text, unsigned& charsLeft, unsigned maxChars)
{
    if (charsLeft == text.length() && charsLeft <= maxChars) {
        charsLeft = 0;
        return new Text(doc, text);
    }
    
    unsigned start = text.length() - charsLeft;
    unsigned end = start + std::min(charsLeft, maxChars);
    
    // check we are not on an unbreakable boundary
    TextBreakIterator* it = characterBreakIterator(text.characters(), text.length());
    if (end < text.length() && !isTextBreak(it, end))
        end = textBreakPreceding(it, end);
        
    // maxChars of unbreakable characters could lead to infinite loop
    if (end <= start)
        end = text.length();
    
    String nodeText = text.substring(start, end - start);
    charsLeft = text.length() - end;
        
    return new Text(doc, nodeText);
}
예제 #4
0
TextBreakIterator* cursorMovementIterator(const UChar* string, int length)
{
    // FIXME: This needs closer inspection to achieve behaviour identical to the ICU version.
    return characterBreakIterator(string, length);
}
 TextBreakIterator* cursorMovementIterator(const UChar* string, int length)
 {
     return characterBreakIterator(string, length);
 }
예제 #6
0
int CoreTextController::offsetForPosition(int h, bool includePartialGlyphs)
{
    // FIXME: For positions occurring within a ligature, we should return the closest "ligature caret" or
    // approximate it by dividing the width of the ligature by the number of characters it encompasses.
    // However, Core Text does not expose a low-level API for directly finding
    // out how many characters a ligature encompasses (the "attachment count").
    if (h >= m_totalWidth)
        return m_run.ltr() ? m_end : 0;
    if (h < 0)
        return m_run.ltr() ? 0 : m_end;

    CGFloat x = h;

    size_t runCount = m_coreTextRuns.size();
    size_t offsetIntoAdjustedGlyphs = 0;

    for (size_t r = 0; r < runCount; ++r) {
        const CoreTextRun& coreTextRun = m_coreTextRuns[r];
        for (unsigned j = 0; j < coreTextRun.glyphCount(); ++j) {
            CGFloat adjustedAdvance = m_adjustedAdvances[offsetIntoAdjustedGlyphs + j].width;
            if (x <= adjustedAdvance) {
                CFIndex hitIndex = coreTextRun.indexAt(j);
                int stringLength = coreTextRun.stringLength();
                TextBreakIterator* characterIterator = characterBreakIterator(coreTextRun.characters(), stringLength);
                int clusterStart;
                if (isTextBreak(characterIterator, hitIndex))
                    clusterStart = hitIndex;
                else {
                    clusterStart = textBreakPreceding(characterIterator, hitIndex);
                    if (clusterStart == TextBreakDone)
                        clusterStart = 0;
                }

                if (!includePartialGlyphs)
                    return coreTextRun.stringLocation() + clusterStart;

                int clusterEnd = textBreakFollowing(characterIterator, hitIndex);
                if (clusterEnd == TextBreakDone)
                    clusterEnd = stringLength;

                CGFloat clusterWidth = adjustedAdvance;
                // FIXME: The search stops at the boundaries of coreTextRun. In theory, it should go on into neighboring CoreTextRuns
                // derived from the same CTLine. In practice, we do not expect there to be more than one CTRun in a CTLine, as no
                // reordering and on font fallback should occur within a CTLine.
                if (clusterEnd - clusterStart > 1) {
                    int firstGlyphBeforeCluster = j - 1;
                    while (firstGlyphBeforeCluster && coreTextRun.indexAt(firstGlyphBeforeCluster) >= clusterStart && coreTextRun.indexAt(firstGlyphBeforeCluster) < clusterEnd) {
                        CGFloat width = m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphBeforeCluster].width;
                        clusterWidth += width;
                        x += width;
                        firstGlyphBeforeCluster--;
                    }
                    unsigned firstGlyphAfterCluster = j + 1;
                    while (firstGlyphAfterCluster < coreTextRun.glyphCount() && coreTextRun.indexAt(firstGlyphAfterCluster) >= clusterStart && coreTextRun.indexAt(firstGlyphAfterCluster) < clusterEnd) {
                        clusterWidth += m_adjustedAdvances[offsetIntoAdjustedGlyphs + firstGlyphAfterCluster].width;
                        firstGlyphAfterCluster++;
                    }
                }
                if (x <= clusterWidth / 2)
                    return coreTextRun.stringLocation() + (m_run.ltr() ? clusterStart : clusterEnd);
                else
                    return coreTextRun.stringLocation() + (m_run.ltr() ? clusterEnd : clusterStart);
            }
            x -= adjustedAdvance;
        }
        offsetIntoAdjustedGlyphs += coreTextRun.glyphCount();
    }

    ASSERT_NOT_REACHED();
    return 0;
}