コード例 #1
0
//SAMSUNG_THAI_EDITING_FIX >>
FloatRect Font::selectionRectForComplexText(const TextRun& run,
                                const IntPoint& point, int h, int from, int to) const
{
    SkPaint              paint;
    SkPaint::FontMetrics metrics;
    float beforeWidth = 0.0f ;
    float afterWidth = 0.0f ;

    primaryFont()->platformData().setupPaint(&paint);

    size_t length = from ;
    if (length > 0) {
        beforeWidth = paint.measureText(run.characters(), length << 1);
    }

    length = to ;
    if (length > 0) {
        afterWidth = paint.measureText(run.characters(), length << 1);
    }

    
    return FloatRect(point.x() + floorf(beforeWidth),
                     point.y(),
                     roundf(afterWidth) - floorf(beforeWidth),
                     roundf(SkScalarToFloat(h)));
}
コード例 #2
0
FloatRect Font::selectionRectForComplexText(const TextRun& run,
                                const IntPoint& point, int h, int from, int to) const
{
    SkPaint              paint;
    SkScalar             width, left;
    SkPaint::FontMetrics metrics;

    primaryFont()->platformData().setupPaint(&paint);

    SkScalar spacing = paint.getFontMetrics(&metrics);

    float beforeWidth = SkScalarToFloat(paint.measureText(run.characters(), from << 1));
    float afterWidth = SkScalarToFloat(paint.measureText(run.characters(), to << 1));

    if (run.rtl()) {
    	float totalWidth = SkScalarToFloat(paint.measureText(run.characters(), run.length() << 1));
    	return FloatRect(point.x() + floorf(totalWidth - afterWidth),
    	                 point.y(),
                         roundf(totalWidth - beforeWidth) - floorf(totalWidth - afterWidth),
    	                 //roundf(SkScalarToFloat(spacing))); // Don't compute rect height, but use h.
                         h);
    } else {
        return FloatRect(point.x() + floorf(beforeWidth),
                         point.y(),
                         roundf(afterWidth) - floorf(beforeWidth),
                         //roundf(SkScalarToFloat(spacing))); // Don't compute rect height, but use h.
                         h);
    }
}
コード例 #3
0
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */) const
{
    void* font = 0;
    float w = 0.f;
    const UChar* str = 0;
    UChar c = 0;
    const SimpleFontData* sfont = primaryFont();
    float scale = 0;
    int i, len;

    if (!sfont) return 0.f;

    len = run.length();
    if (!len) return 0.f;

    str = run.characters();

    font = sfont->platformData().Font();
    if (!font) return 0.f;
    scale = sfont->platformData().scale();

    for (i=0; i<len; i++) {
        c = fixedChar(str[i]);
        if (!c) continue;
        w += (float)wkcFontGetCharWidthPeer(font, c) * scale;
    }

    return w;
}
コード例 #4
0
int Font::offsetForPositionForComplexText(const TextRun& run, int x,
                                          bool includePartialGlyphs) const
{
    SkPaint                         paint;
    int                             count = run.length();
    SkAutoSTMalloc<64, SkScalar>    storage(count);
    SkScalar*                       widths = storage.get();
    SkAutoSTMalloc<64, int>    storageClusterIndex(count);
    int*                       clusterIndex = storageClusterIndex.get();

    primaryFont()->platformData().setupPaint(&paint);

    //count = paint.getTextWidths(run.characters(), count << 1, widths);
    count = paint.getComplexTextWidths(run.characters(), count << 1, widths, clusterIndex);

    if (count > 0)
    {
        SkScalar pos = 0;
        for (int i = 0; i < count; i++)
        {
            if (x < SkScalarRound(pos + SkScalarHalf(widths[i])))
                return clusterIndex[i];
            pos += widths[i];
        }
    }
    return run.length();
}
コード例 #5
0
int Font::offsetForPositionForSimpleText(const TextRun& run, int position, bool includePartialGlyphs) const
{
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
    String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
    QString string = fromRawDataWithoutRef(sanitized);

    QFontMetrics fm(font());
    float delta = (float)position;
    int curPos = 0;
    do {
        float charWidth = fm.width(string[curPos]);
        delta -= charWidth;
        if (includePartialGlyphs) {
            if (delta + charWidth / 2 <= 0)
                break;
        } else {
            if (delta + charWidth <= 0)
                break;
        }
    } while (++curPos < string.size());

    return curPos;
#else
    Q_ASSERT(false);
    return 0;
#endif
}
コード例 #6
0
ファイル: FontPango.cpp プロジェクト: conioh/os-design
int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat, bool includePartialGlyphs) const
{
#if USE(FREETYPE)
    if (!primaryFont()->platformData().m_pattern)
        return offsetForPositionForSimpleText(run, xFloat, includePartialGlyphs);
#endif
    // FIXME: This truncation is not a problem for HTML, but only affects SVG, which passes floating-point numbers
    // to Font::offsetForPosition(). Bug http://webkit.org/b/40673 tracks fixing this problem.
    int x = static_cast<int>(xFloat);

    PangoLayout* layout = getDefaultPangoLayout(run);
    setPangoAttributes(this, run, layout);

    gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
    pango_layout_set_text(layout, utf8, -1);

    int index, trailing;
    pango_layout_xy_to_index(layout, x * PANGO_SCALE, 1, &index, &trailing);
    glong offset = g_utf8_pointer_to_offset(utf8, utf8 + index);
    if (includePartialGlyphs)
        offset += trailing;

    g_free(utf8);
    g_object_unref(layout);

    return offset;
}
コード例 #7
0
ファイル: FontLinux.cpp プロジェクト: DreamOnTheGo/src
    TextRunWalker(const TextRun& run, unsigned startingX, const Font* font)
        : m_font(font)
        , m_run(run)
        , m_startingX(startingX)
        , m_offsetX(m_startingX)
        , m_iterateBackwards(run.rtl())
    {
        memset(&m_item, 0, sizeof(m_item));
        // We cannot know, ahead of time, how many glyphs a given script run
        // will produce. We take a guess that script runs will not produce more
        // than twice as many glyphs as there are code points and fallback if
        // we find that we are wrong.
        m_maxGlyphs = run.length() * 2;
        createGlyphArrays();

        m_item.log_clusters = new unsigned short[run.length()];

        m_item.face = 0;
        m_item.font = allocHarfbuzzFont();

        m_item.string = run.characters();
        m_item.stringLength = run.length();
        m_item.item.bidiLevel = run.rtl();

        reset();
    }
コード例 #8
0
ファイル: FontGdkApollo.cpp プロジェクト: UIKit0/WebkitAIR
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const TextStyle& style, const FloatPoint& point, int from, int to) const
{
    cairo_t* cr = context->platformContext();
    cairo_save(cr);
    
    PangoLayout* layout = pango_cairo_create_layout(cr);
    
    gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), from, run.length());
    pango_layout_set_text(layout, utf8, -1);
    
    setPangoAttributes(this, run, layout, style.rtl());
    
    // Set the text color to use for drawing.
    float red, green, blue, alpha;
    Color penColor = context->fillColor();
    penColor.getRGBA(red, green, blue, alpha);
    cairo_set_source_rgba(cr, red, green, blue, alpha);
    
    cairo_move_to(cr, point.x(), point.y());
    PangoLayoutLine* layoutLine = pango_layout_get_line(layout, 0);
    pango_cairo_show_layout_line(cr, layoutLine);
    g_free(utf8);

    g_object_unref(layout);
    cairo_restore(cr);
}
コード例 #9
0
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
#if defined(USE_FREETYPE)
    if (!primaryFont()->platformData().m_pattern) {
        drawSimpleText(context, run, point, from, to);
        return;
    }
#endif

    cairo_t* cr = context->platformContext();
    PangoLayout* layout = pango_cairo_create_layout(cr);
    setPangoAttributes(this, run, layout);

    gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
    pango_layout_set_text(layout, utf8, -1);

    // Our layouts are single line
    PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0);

    // Get the region where this text will be laid out. We will use it to clip
    // the Cairo context, for when we are only painting part of the text run and
    // to calculate the size of the shadow buffer.
    PangoRegionType partialRegion = 0;
    char* start = g_utf8_offset_to_pointer(utf8, from);
    char* end = g_utf8_offset_to_pointer(start, to - from);
    int ranges[] = {start - utf8, end - utf8};
    partialRegion = gdk_pango_layout_line_get_clip_region(layoutLine, 0, 0, ranges, 1);

    drawGlyphsShadow(context, cr, point, layoutLine, partialRegion);

    cairo_save(cr);
    cairo_translate(cr, point.x(), point.y());

    float red, green, blue, alpha;
    context->fillColor().getRGBA(red, green, blue, alpha);
    cairo_set_source_rgba(cr, red, green, blue, alpha);
    gdk_cairo_region(cr, partialRegion);
    cairo_clip(cr);

    pango_cairo_show_layout_line(cr, layoutLine);

    if (context->textDrawingMode() & TextModeStroke) {
        Color strokeColor = context->strokeColor();
        strokeColor.getRGBA(red, green, blue, alpha);
        cairo_set_source_rgba(cr, red, green, blue, alpha);
        pango_cairo_layout_line_path(cr, layoutLine);
        cairo_set_line_width(cr, context->strokeThickness());
        cairo_stroke(cr);
    }

    // Pango sometimes leaves behind paths we don't want
    cairo_new_path(cr);

    destroyPangoRegion(partialRegion);
    g_free(utf8);
    g_object_unref(layout);

    cairo_restore(cr);
}
コード例 #10
0
ファイル: FontQt.cpp プロジェクト: jackiekaon/owb-mirror
void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const TextStyle&, const FloatPoint& point) const
{
    // FIXME: style, run.from()/length() cut-off
    ctx->platformContext()->drawText(point, 
                                     QString::fromRawData(
                                         reinterpret_cast<const QChar*>(
                                             run.characters() + run.from()), run.length()));
}
コード例 #11
0
ファイル: FontQt.cpp プロジェクト: akosicki/phantomjs
int Font::offsetForPositionForComplexText(const TextRun& run, float position, bool) const
{
    String sanitized = Font::normalizeSpaces(run.characters(), run.length());
    QString string = fromRawDataWithoutRef(sanitized);

    QTextLayout layout(string, font());
    QTextLine line = setupLayout(&layout, run);
    return line.xToCursor(position);
}
コード例 #12
0
ファイル: FontQt.cpp プロジェクト: akosicki/phantomjs
FloatRect Font::selectionRectForSimpleText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const
{
    String sanitized = Font::normalizeSpaces(run.characters(), run.length());
    QString wholeText = fromRawDataWithoutRef(sanitized);
    QString selectedText = fromRawDataWithoutRef(sanitized, from, qMin(to - from, wholeText.length() - from));

    int startX = QFontMetrics(font()).width(wholeText, from, Qt::TextBypassShaping);
    int width = QFontMetrics(font()).width(selectedText, -1, Qt::TextBypassShaping);

    return FloatRect(pt.x() + startX, pt.y(), width, h);
}
コード例 #13
0
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*) const
{
    SkPaint paint;

    primaryFont()->platformData().setupPaint(&paint);

//printf("--------- complext measure %d chars\n", run.to() - run.from());

    SkScalar width = paint.measureText(run.characters(), run.length() << 1);
    return SkScalarToFloat(width);
}
コード例 #14
0
ファイル: FontQt.cpp プロジェクト: Fale/qtmoko
static QString qstring(const TextRun& run)
{
    QString string((QChar *)run.characters(), run.length());
    QChar *uc = string.data();
    for (int i = 0; i < string.length(); ++i) {
        if (Font::treatAsSpace(uc[i].unicode()))
            uc[i] = 0x20;
        else if (Font::treatAsZeroWidthSpace(uc[i].unicode()))
            uc[i] = 0x200c;
    }
    return string;
}
コード例 #15
0
ファイル: FontGdkApollo.cpp プロジェクト: UIKit0/WebkitAIR
static float getWidth(PangoLayout *layout, const TextRun& run, int from, int to)
{
    int layoutWidth;

    gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), from, to);
    pango_layout_set_text(layout, utf8, -1);
    g_free(utf8);
    pango_layout_get_size(layout, &layoutWidth, 0);
    float width = (float)layoutWidth / (double)PANGO_SCALE;

    return width;
}
コード例 #16
0
ファイル: FontQt.cpp プロジェクト: akosicki/phantomjs
FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& pt, int h, int from, int to) const
{
    String sanitized = Font::normalizeSpaces(run.characters(), run.length());
    QString string = fromRawDataWithoutRef(sanitized);

    QTextLayout layout(string, font());
    QTextLine line = setupLayout(&layout, run);

    float x1 = line.cursorToX(from);
    float x2 = line.cursorToX(to);
    if (x2 < x1)
        qSwap(x1, x2);

    return FloatRect(pt.x() + x1, pt.y(), x2 - x1, h);
}
コード例 #17
0
FloatRect Font::selectionRectForSimpleText(const TextRun& run, const IntPoint& pt, int h, int from, int to) const
{
#if QT_VERSION >= QT_VERSION_CHECK(4, 7, 0)
    String sanitized = Font::normalizeSpaces(String(run.characters(), run.length()));
    QString wholeText = fromRawDataWithoutRef(sanitized);
    QString selectedText = fromRawDataWithoutRef(sanitized, from, to - from);

    int startX = QFontMetrics(font()).width(wholeText, from, Qt::TextBypassShaping);
    int width = QFontMetrics(font()).width(selectedText, -1, Qt::TextBypassShaping);

    return FloatRect(pt.x() + startX, pt.y(), width, h);
#else
    Q_ASSERT(false);
    return FloatRect();
#endif
}
コード例 #18
0
SVGTextMetrics::SVGTextMetrics(const Font& font, const TextRun& run, unsigned position, unsigned textLength)
    : m_width(0)
    , m_height(0)
    , m_length(0)
{
    int extraCharsAvailable = textLength - (position + run.length());
    int length = 0;

    m_width = font.floatWidth(run, extraCharsAvailable, length, m_glyph.name);
    m_height = font.fontMetrics().height();
    m_glyph.unicodeString = String(run.characters(), length);
    m_glyph.isValid = true;

    ASSERT(length >= 0);
    m_length = static_cast<unsigned>(length);
}
コード例 #19
0
ファイル: FontGdkApollo.cpp プロジェクト: UIKit0/WebkitAIR
int Font::offsetForPositionForComplexText(const TextRun& run, const TextStyle& style, int x, bool includePartialGlyphs) const
{
    PangoLayout* layout = getDefaultPangoLayout(run);
    setPangoAttributes(this, run, layout, style.rtl());

    gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
    pango_layout_set_text(layout, utf8, -1);

    int index, trailing;
    pango_layout_xy_to_index(layout, x * PANGO_SCALE, 1, &index, &trailing);
    glong offset = g_utf8_pointer_to_offset(utf8, utf8 + index);
    g_object_unref(layout);
    g_free(utf8);

    return offset;
}
コード例 #20
0
FloatRect Font::selectionRectForComplexText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
{
    void* font = 0;
    const UChar* str = 0;
    const SimpleFontData* sfont = 0;
    int i, len;
    float x0,x1,x2;
    float scale = 0;
    UChar c = 0;

    len = run.length();
    if (!len) return FloatRect();
    if (from>=len || to>len) return FloatRect();
    if (from>=to) return FloatRect();
    if (from<0) from = 0;
    if (to>len) to = len;

    str = run.characters();
    sfont = primaryFont();
    if (!sfont) return FloatRect();
    font = sfont->platformData().Font();
    if (!font) return FloatRect();
    scale = sfont->platformData().scale();

    x0=x1=x2=0;
    for (i=0; i<from; i++) {
        c = fixedChar(str[i]);
        if (!c) continue;
        x0 += ((float)wkcFontGetCharWidthPeer(font, c) * scale);
    }
    for (i=from; i<to; i++) {
        c = fixedChar(str[i]);
        if (!c) continue;
        x1 += ((float)wkcFontGetCharWidthPeer(font, c) * scale);
    }
    for (i=to; i<len; i++) {
        c = fixedChar(str[i]);
        if (!c) continue;
        x2 += ((float)wkcFontGetCharWidthPeer(font, c) * scale);
    }

    if (run.rtl()) {
        return FloatRect(point.x() + x2, point.y(), x1, h);
    } else {
        return FloatRect(point.x() + x0, point.y(), x1, h);
    }
}
コード例 #21
0
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*) const
{
#if 0
    SkPaint paint;

    primaryFont()->platformData().setupPaint(&paint);

//printf("--------- complext measure %d chars\n", run.to() - run.from());

    SkScalar width = paint.measureText(run.characters(), run.length() << 1);
    return SkScalarToFloat(width);
#else
	WidthIterator it(this, run);
    it.advance(run.length());
    return SkScalarToFloat(it.m_runWidthSoFar);
#endif
}
コード例 #22
0
void Font::drawComplexText(GraphicsContext* gc, TextRun const& run,
                           FloatPoint const& point, int, int) const
{
    SkCanvas*   canvas = gc->platformContext()->mCanvas;
    SkPaint     paint;

    if (!setupForText(&paint, gc, primaryFont())) {
        return;
    }

    // go to chars, instead of glyphs, which was set by setupForText()
    paint.setTextEncoding(SkPaint::kUTF16_TextEncoding);

    canvas->drawText(run.characters(), run.length() << 1,
                     SkFloatToScalar(point.x()), SkFloatToScalar(point.y()),
                     paint);
}
コード例 #23
0
FloatRect Font::selectionRectForComplexText(const TextRun& run,
                                const IntPoint& point, int h, int, int) const
{
    SkPaint              paint;
    SkScalar             width, left;
    SkPaint::FontMetrics metrics;

    primaryFont()->platformData().setupPaint(&paint);

    width = paint.measureText(run.characters(), run.length() << 1);
    SkScalar spacing = paint.getFontMetrics(&metrics);
    
    return FloatRect(point.x(),
					 point.y() - floorf(SkScalarToFloat(-metrics.fAscent)),
                     roundf(SkScalarToFloat(width)),
                     roundf(SkScalarToFloat(spacing)));
}
コード例 #24
0
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();
}
コード例 #25
0
ファイル: FontGtk.cpp プロジェクト: Czerrr/ISeeBrowser
float Font::floatWidthForComplexText(const TextRun& run) const
{
    if (run.length() == 0)
        return 0.0f;

    PangoLayout* layout = getDefaultPangoLayout(run);
    setPangoAttributes(this, run, layout);

    gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
    pango_layout_set_text(layout, utf8, -1);

    int width;
    pango_layout_get_pixel_size(layout, &width, 0);

    g_free(utf8);
    g_object_unref(layout);

    return width;
}
コード例 #26
0
ファイル: FontGdkApollo.cpp プロジェクト: UIKit0/WebkitAIR
float Font::floatWidthForComplexText(const TextRun& run, const TextStyle& style) const
{
    if (run.length() == 0)
        return 0.0f;

    PangoLayout* layout = getDefaultPangoLayout(run);
    setPangoAttributes(this, run, layout, style.rtl());

    gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
    pango_layout_set_text(layout, utf8, -1);
    g_free(utf8);

    int layoutWidth;
    pango_layout_get_size(layout, &layoutWidth, 0);
    float width = (float)layoutWidth / (double)PANGO_SCALE;
    g_object_unref(layout);

    return width;
}
コード例 #27
0
ファイル: FontQt.cpp プロジェクト: akosicki/phantomjs
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();
}
コード例 #28
0
ファイル: FontPango.cpp プロジェクト: conioh/os-design
FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
{
#if USE(FREETYPE)
    if (!primaryFont()->platformData().m_pattern)
        return selectionRectForSimpleText(run, point, h, from, to);
#endif

    PangoLayout* layout = getDefaultPangoLayout(run);
    setPangoAttributes(this, run, layout);

    gchar* utf8 = convertUniCharToUTF8(run.characters(), run.length(), 0, run.length());
    pango_layout_set_text(layout, utf8, -1);

    char* start = g_utf8_offset_to_pointer(utf8, from);
    char* end = g_utf8_offset_to_pointer(start, to - from);

    if (run.ltr()) {
        from = start - utf8;
        to = end - utf8;
    } else {
        from = end - utf8;
        to = start - utf8;
    }

    PangoLayoutLine* layoutLine = pango_layout_get_line_readonly(layout, 0);
    int xPos;

    xPos = 0;
    if (from < layoutLine->length)
        pango_layout_line_index_to_x(layoutLine, from, FALSE, &xPos);
    float beforeWidth = PANGO_PIXELS_FLOOR(xPos);

    xPos = 0;
    if (run.ltr() || to < layoutLine->length)
        pango_layout_line_index_to_x(layoutLine, to, FALSE, &xPos);
    float afterWidth = PANGO_PIXELS(xPos);

    g_free(utf8);
    g_object_unref(layout);

    return FloatRect(point.x() + beforeWidth, point.y(), afterWidth - beforeWidth, h);
}
コード例 #29
0
SVGTextMetrics::SVGTextMetrics(RenderSVGInlineText* textRenderer, const TextRun& run)
{
    ASSERT(textRenderer);

    float scalingFactor = textRenderer->scalingFactor();
    ASSERT(scalingFactor);

    const Font& scaledFont = textRenderer->scaledFont();
    int length = 0;

    // Calculate width/height using the scaled font, divide this result by the scalingFactor afterwards.
    m_width = scaledFont.width(run, length, m_glyph.name) / scalingFactor;
    m_height = scaledFont.fontMetrics().floatHeight() / scalingFactor;

    m_glyph.unicodeString = String(run.characters(), length);
    m_glyph.isValid = true;

    ASSERT(length >= 0);
    m_length = static_cast<unsigned>(length);
}
コード例 #30
0
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
}