Пример #1
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);
}
QFont Font::font() const
{
    QFont f = primaryFont()->getQtFont();
    if (m_letterSpacing != 0)
        f.setLetterSpacing(QFont::AbsoluteSpacing, m_letterSpacing);
    if (m_wordSpacing != 0)
        f.setWordSpacing(m_wordSpacing);
    return f;
}
Пример #3
0
bool Font::primaryFontHasGlyphForCharacter(UChar32 character) const
{
    unsigned pageNumber = (character / GlyphPage::size);

    GlyphPageTreeNode* node = GlyphPageTreeNode::getRootChild(primaryFont(), pageNumber);
    GlyphPage* page = node->page();

    return page && page->fontDataForCharacter(character);
}
Пример #4
0
float Font::floatWidth(const TextRun& run) const
{
#if ENABLE(SVG_FONTS)
    if (primaryFont()->isSVGFont())
        return floatWidthUsingSVGFont(run);
#endif

    if (canUseGlyphCache(run))
        return floatWidthForSimpleText(run, 0);
    return floatWidthForComplexText(run);
}
Пример #5
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);
}
Пример #6
0
QFont Font::font() const
{
    QFont f = primaryFont()->getQtFont();
    f.setWeight(toQFontWeight(weight()));
    f.setItalic(italic());
    if (m_letterSpacing != 0)
        f.setLetterSpacing(QFont::AbsoluteSpacing, m_letterSpacing);
    if (m_wordSpacing != 0)
        f.setWordSpacing(m_wordSpacing);
    return f;
}
Пример #7
0
int Font::offsetForPosition(const TextRun& run, int x, bool includePartialGlyphs) const
{
#if ENABLE(SVG_FONTS)
    if (primaryFont()->isSVGFont())
        return offsetForPositionForTextUsingSVGFont(run, x, includePartialGlyphs);
#endif

    if (canUseGlyphCache(run))
        return offsetForPositionForSimpleText(run, x, includePartialGlyphs);
    return offsetForPositionForComplexText(run, x, includePartialGlyphs);
}
Пример #8
0
SVGFontElement* Font::svgFont() const
{ 
    if (!isSVGFont())
        return 0;

    SVGFontElement* fontElement = 0;
    SVGFontFaceElement* fontFaceElement = 0;
    if (svgFontAndFontFaceElementForFontData(primaryFont(), fontFaceElement, fontElement))
        return fontElement;
    
    return 0;
}
Пример #9
0
FloatRect Font::selectionRectForText(const TextRun& run, const IntPoint& point, int h, int from, int to) const
{
#if ENABLE(SVG_FONTS)
    if (primaryFont()->isSVGFont())
        return selectionRectForTextUsingSVGFont(run, point, h, from, to);
#endif

    to = (to == -1 ? run.length() : to);
    if (canUseGlyphCache(run))
        return selectionRectForSimpleText(run, point, h, from, to);
    return selectionRectForComplexText(run, point, h, from, to);
}
Пример #10
0
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow*) const
{
    if (run.length() == 0)
        return run.padding();

    const FontPlatformData& fontPlatformData = primaryFont()->platformData();
    const float scaleFactor = fontPlatformData.scaleFactor();
    Olympia::Platform::Text::Font* font = fontPlatformData.font();
    Olympia::Platform::Text::DrawParam drawParam;

    String sanitized = setupTextDrawing(this, run, &drawParam);

    // WebKit calls us with plain spaces almost half of the time.
    // Exit early with a cached value to avoid lots of calls into Text API.
    if (sanitized.length() == 1 && sanitized[0] == ' ')
        return primaryFont()->spaceWidth();

#if PLATFORM(EGL) // FIXME: remove after Text API fixes shared context handling
    if (eglGetCurrentContext() == EGL_NO_CONTEXT)
        EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCurrent();
#endif
    Olympia::Platform::Text::TextMetrics metrics;
    FontPlatformData::engine()->drawText(0 /* no drawing, only measuring */,
        *font, sanitized.characters(), sanitized.length(), 0 /*x*/, 0 /*y*/,
        0 /* no wrap */, &drawParam, &metrics);

    if (fallbackFonts && primaryFont()->lineSpacing() < metrics.m_ascent + metrics.m_descent) {
        FontPlatformData tallerFontPlatformData = fontPlatformData;
        tallerFontPlatformData.setLineSpacingOverride(metrics.m_ascent, metrics.m_descent);

        // HACK: We can't generate a cached SimpleFontData from outside of FontCache,
        //   so instead we abuse FontCache::getFontDataForCharacters() to do that.
        //   Safe to use this way because we also pass 0 as string length,
        //   which avoids clashes with possible regular calls of that method.
        fallbackFonts->add(fontCache()->getFontDataForCharacters(*this,
            reinterpret_cast<const UChar*>(&tallerFontPlatformData), 0));
    }

    return metrics.m_linearAdvance * scaleFactor;
}
Пример #11
0
float Font::floatWidth(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const
{
#if ENABLE(SVG_FONTS)
    if (primaryFont()->isSVGFont())
        return floatWidthUsingSVGFont(run, extraCharsAvailable, charsConsumed, glyphName);
#endif

    charsConsumed = run.length();
    glyphName = "";
    if (canUseGlyphCache(run))
        return floatWidthForSimpleText(run, 0);
    return floatWidthForComplexText(run);
}
Пример #12
0
void FontFallbackList::determinePitch(const Font* font) const
{
    const FontData* fontData = primaryFont(font);
    if (!fontData->isSegmented())
        m_pitch = static_cast<const SimpleFontData*>(fontData)->pitch();
    else {
        const SegmentedFontData* segmentedFontData = static_cast<const SegmentedFontData*>(fontData);
        unsigned numRanges = segmentedFontData->numRanges();
        if (numRanges == 1)
            m_pitch = segmentedFontData->rangeAt(0).fontData()->pitch();
        else
            m_pitch = VariablePitch;
    }
}
Пример #13
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);
    }
}
Пример #14
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)));
}
Пример #15
0
void Font::drawComplexText(GraphicsContext* graphicsContext,
    const TextRunPaintInfo& runInfo,
    const FloatPoint& point) const
{
    UniscribeHelperTextRun state(runInfo.run, *this);

    SkColor color = graphicsContext->effectiveFillColor();
    unsigned char alpha = SkColorGetA(color);
    // Skip 100% transparent text; no need to draw anything.
    if (!alpha && graphicsContext->strokeStyle() == NoStroke)
        return;

    HDC hdc = 0;
    // Uniscribe counts the coordinates from the upper left, while WebKit uses
    // the baseline, so we have to subtract off the ascent.
    state.draw(graphicsContext, primaryFont()->platformData(), hdc, lroundf(point.x()), lroundf(point.y() - fontMetrics().ascent()), runInfo.bounds, runInfo.from, runInfo.to);
}
Пример #16
0
float Font::width(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
#if ENABLE(SVG_FONTS)
    if (primaryFont()->isSVGFont())
        return floatWidthUsingSVGFont(run);
#endif

    CodePath codePathToUse = codePath(run);
    if (codePathToUse != Complex) {
        // If the complex text implementation cannot return fallback fonts, avoid
        // returning them for simple text as well.
        static bool returnFallbackFonts = canReturnFallbackFontsForComplexText();
        return floatWidthForSimpleText(run, 0, returnFallbackFonts ? fallbackFonts : 0, codePathToUse == SimpleWithGlyphOverflow || (glyphOverflow && glyphOverflow->computeBounds) ? glyphOverflow : 0);
    }

    return floatWidthForComplexText(run, fallbackFonts, glyphOverflow);
}
Пример #17
0
float Font::width(const TextRun& run, int extraCharsAvailable, int& charsConsumed, String& glyphName) const
{
#if !ENABLE(SVG_FONTS)
    UNUSED_PARAM(extraCharsAvailable);
#else
    if (primaryFont()->isSVGFont())
        return floatWidthUsingSVGFont(run, extraCharsAvailable, charsConsumed, glyphName);
#endif

    charsConsumed = run.length();
    glyphName = "";

    if (codePath(run) != Complex)
        return floatWidthForSimpleText(run, 0);

    return floatWidthForComplexText(run);
}
Пример #18
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);
}
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
}
Пример #20
0
int Font::offsetForPosition(const TextRun& run, float x, bool includePartialGlyphs) const
{
#if ENABLE(SVG_FONTS)
    if (primaryFont()->isSVGFont())
        return offsetForPositionForTextUsingSVGFont(run, x, includePartialGlyphs);
#endif

#if USE(WRATH)
    //return DrawnTextOfWRATH::offsetForPosition(*this, run, x, includePartialGlyphs);
#endif

    if (codePath(run) != Complex)
        return offsetForPositionForSimpleText(run, x, includePartialGlyphs);

    return offsetForPositionForComplexText(run, x, includePartialGlyphs);

}
Пример #21
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();
}
Пример #22
0
void Font::drawEmphasisMarks(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
{
    if (loadingCustomFonts())
        return;

    if (to < 0)
        to = run.length();

#if ENABLE(SVG_FONTS)
    // FIXME: Implement for SVG fonts.
    if (primaryFont()->isSVGFont())
        return;
#endif

    if (codePath(run) != Complex)
        drawEmphasisMarksForSimpleText(context, run, mark, point, from, to);
    else
        drawEmphasisMarksForComplexText(context, run, mark, point, from, to);
}
Пример #23
0
FloatRect Font::selectionRectForText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
{
#if ENABLE(SVG_FONTS)
    if (primaryFont()->isSVGFont())
        return selectionRectForTextUsingSVGFont(run, point, h, from, to);
#endif

    to = (to == -1 ? run.length() : to);

#if USE(WRATH)
    return DrawnTextOfWRATH::selectionRectForText(*this, run, point, h, from, to);
#endif

    if (codePath(run) != Complex)
        return selectionRectForSimpleText(run, point, h, from, to);

    return selectionRectForComplexText(run, point, h, from, to);

}
Пример #24
0
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);
}
Пример #25
0
void Font::drawText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
    // Don't draw anything while we are using custom fonts that are in the process of loading.
    if (loadingCustomFonts())
        return;
    
    to = (to == -1 ? run.length() : to);

#if ENABLE(SVG_FONTS)
    if (primaryFont()->isSVGFont()) {
        drawTextUsingSVGFont(context, run, point, from, to);
        return;
    }
#endif

    if (codePath(run) != Complex)
        return drawSimpleText(context, run, point, from, to);

    return drawComplexText(context, run, point, from, to);
}
Пример #26
0
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
{
    if (!primaryFont()->platformData().size())
        return 0;

    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();
}
Пример #27
0
int Font::offsetForPositionForComplexText(const TextRun& run, float position, bool includePartialGlyphs) const
{
    // In here, we determine the cursor index for an x (mouse-click) position.
    const FontPlatformData& fontPlatformData = primaryFont()->platformData();
    const float scaleFactor = fontPlatformData.scaleFactor();
    Olympia::Platform::Text::Font* font = fontPlatformData.font();
    Olympia::Platform::Text::DrawParam drawParam;

    String sanitized = setupTextDrawing(this, run, &drawParam);

#if PLATFORM(EGL) // FIXME: remove after Text API fixes shared context handling
    if (eglGetCurrentContext() == EGL_NO_CONTEXT)
        EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCurrent();
#endif
    int offset;
    FontPlatformData::engine()->xToTextPos(position / scaleFactor, offset,
        Olympia::Platform::Text::TextPosRoundNearest, *font,
        sanitized.characters(), sanitized.length(), drawParam);

    return offset;
}
Пример #28
0
FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int height, int from, int to, int width) const
{
    const FontPlatformData& fontPlatformData = primaryFont()->platformData();
    const float scaleFactor = fontPlatformData.scaleFactor();
    Olympia::Platform::Text::Font* font = fontPlatformData.font();
    Olympia::Platform::Text::DrawParam drawParam;

    String sanitized = setupTextDrawing(this, run, &drawParam);
    adjustOffsetsForTextDrawing(run, from, to);

#if PLATFORM(EGL) // FIXME: remove after Text API fixes shared context handling
    if (eglGetCurrentContext() == EGL_NO_CONTEXT)
        EGLDisplayOpenVG::current()->sharedPlatformSurface()->makeCurrent();
#endif
    double fromX;
    FontPlatformData::engine()->textPosToX(from, fromX, *font,
        sanitized.characters(), sanitized.length(), drawParam);
    ASSERT_VG_NO_ERROR();
    fromX *= scaleFactor;

    double toX;
    FontPlatformData::engine()->textPosToX(to, toX, *font,
        sanitized.characters(), sanitized.length(), drawParam);
    ASSERT_VG_NO_ERROR();
    toX *= scaleFactor;

    if (width) {
        double bound = width * scaleFactor;
        if (from == run.length())
            fromX = bound;
        if (to == run.length())
            toX = bound;
    }

    return (toX > fromX)
        ? FloatRect(point.x() + fromX, point.y(), toX - fromX, height)
        : FloatRect(point.x() + toX, point.y(), fromX - toX, height);
}
Пример #29
0
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* overflow) const
{
#if USE(FREETYPE)
    if (!primaryFont()->platformData().m_pattern)
        return floatWidthForSimpleText(run, 0, fallbackFonts, overflow);
#endif

    if (!run.length())
        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;
}
Пример #30
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();

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

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

    if (count > 0)
    {
        SkScalar pos = 0;
        for (int i = 0; i < count; i++)
        {
            if (x < SkScalarRound(pos + SkScalarHalf(widths[i])))
                return i;
            pos += widths[i];
        }
    }
    return count;
}