Esempio n. 1
0
void SHAPE2::compute(DspBuffer& dspbuf) //final
{
    float pad = _dbd._inputPad;
    int inumframes = dspbuf._numframes;
    float* ubuf = dspbuf.channel(0);
    float amt = _param[0].eval();
    _fval[0] = amt;
    if(1) for( int i=0; i<inumframes; i++ )
    {   float s1 = shaper(ubuf[i]*pad,amt);
        float s2 = shaper(s1,amt*0.75);
        ubuf[i] = s2;
    }
}
Esempio n. 2
0
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* /* fallbackFonts */, GlyphOverflow* /* glyphOverflow */) const
{
    HarfBuzzShaper shaper(this, run);
    if (!shaper.shape())
        return 0;
    return shaper.totalWidth();
}
Esempio n. 3
0
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
#if PLATFORM(CHROMIUM)
    if (preferHarfBuzz(this)) {
        GlyphBuffer glyphBuffer;
        HarfBuzzShaper shaper(this, run);
        shaper.setDrawRange(from, to);
        if (shaper.shape(&glyphBuffer)) {
            drawGlyphBuffer(context, run, glyphBuffer, point);
            return;
        }
    }
#endif
    // This glyph buffer holds our glyphs + advances + font data for each glyph.
    GlyphBuffer glyphBuffer;

    float startX = point.x() + getGlyphsAndAdvancesForComplexText(run, from, to, glyphBuffer);

    // We couldn't generate any glyphs for the run.  Give up.
    if (glyphBuffer.isEmpty())
        return;

    // Draw the glyph buffer now at the starting point returned in startX.
    FloatPoint startPoint(startX, point.y());
    drawGlyphBuffer(context, run, glyphBuffer, startPoint);
}
Esempio n. 4
0
float Font::getGlyphsAndAdvancesForComplexText(const TextRunPaintInfo& runInfo, GlyphBuffer& glyphBuffer, ForTextEmphasisOrNot forTextEmphasis) const
{
    HarfBuzzShaper shaper(this, runInfo.run, HarfBuzzShaper::ForTextEmphasis);
    shaper.setDrawRange(runInfo.from, runInfo.to);
    shaper.shape(&glyphBuffer);
    return 0;
}
Esempio n. 5
0
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabicThaiHanLatin) {
  UChar mixedString[] = {0x628, 0x64A, 0x629, 0xE20, 0x65E5, 0x62};
  TextRun mixed(mixedString, 6);
  HarfBuzzShaper shaper(&font, mixed);
  RefPtr<ShapeResult> result = shaper.shapeResult();

  ASSERT_EQ(4u, testInfo(result)->numberOfRunsForTesting());
  ASSERT_TRUE(
      testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script));
  EXPECT_EQ(0u, startIndex);
  EXPECT_EQ(3u, numGlyphs);
  EXPECT_EQ(HB_SCRIPT_ARABIC, script);

  ASSERT_TRUE(
      testInfo(result)->runInfoForTesting(1, startIndex, numGlyphs, script));
  EXPECT_EQ(3u, startIndex);
  EXPECT_EQ(1u, numGlyphs);
  EXPECT_EQ(HB_SCRIPT_THAI, script);

  ASSERT_TRUE(
      testInfo(result)->runInfoForTesting(2, startIndex, numGlyphs, script));
  EXPECT_EQ(4u, startIndex);
  EXPECT_EQ(1u, numGlyphs);
  EXPECT_EQ(HB_SCRIPT_HAN, script);

  ASSERT_TRUE(
      testInfo(result)->runInfoForTesting(3, startIndex, numGlyphs, script));
  EXPECT_EQ(5u, startIndex);
  EXPECT_EQ(1u, numGlyphs);
  EXPECT_EQ(HB_SCRIPT_LATIN, script);
}
// Tests that filling a glyph buffer for a specific range returns the same
// results when shaping word by word as when shaping the full run in one go.
TEST_F(CachingWordShaperTest, CommonAccentRightToLeftFillGlyphBuffer)
{
    // "[] []" with an accent mark over the last square bracket.
    const UChar str[] = { 0x5B, 0x5D, 0x20, 0x5B, 0x301, 0x5D, 0x0 };
    TextRun textRun(str, 6);
    textRun.setDirection(RTL);

    CachingWordShaper shaper(cache.get());
    GlyphBuffer glyphBuffer;
    shaper.fillGlyphBuffer(&font, textRun, fallbackFonts, &glyphBuffer, 1, 6);

    OwnPtr<ShapeCache> referenceCache = adoptPtr(new ShapeCache());
    CachingWordShaper referenceShaper(referenceCache.get());
    GlyphBuffer referenceGlyphBuffer;
    font.setCanShapeWordByWordForTesting(false);
    referenceShaper.fillGlyphBuffer(&font, textRun, fallbackFonts,
        &referenceGlyphBuffer, 1, 6);

    ASSERT_EQ(5u, referenceGlyphBuffer.size());
    ASSERT_EQ(referenceGlyphBuffer.size(), glyphBuffer.size());

    ASSERT_EQ(referenceGlyphBuffer.glyphAt(0), glyphBuffer.glyphAt(0));
    ASSERT_EQ(referenceGlyphBuffer.glyphAt(1), glyphBuffer.glyphAt(1));
    ASSERT_EQ(referenceGlyphBuffer.glyphAt(2), glyphBuffer.glyphAt(2));
    ASSERT_EQ(referenceGlyphBuffer.glyphAt(3), glyphBuffer.glyphAt(3));
    ASSERT_EQ(referenceGlyphBuffer.glyphAt(4), glyphBuffer.glyphAt(4));
}
Esempio n. 7
0
void Font::drawComplexText(GraphicsContext* gc, const TextRun& run,
                           const FloatPoint& point, int from, int to) const
{
    if (!run.length())
        return;

    TextDrawingModeFlags textMode = gc->platformContext()->getTextDrawingMode();
    bool fill = textMode & TextModeFill;
    bool stroke = (textMode & TextModeStroke)
               && gc->platformContext()->getStrokeStyle() != NoStroke
               && gc->platformContext()->getStrokeThickness() > 0;

    if (!fill && !stroke)
        return;

    SkPaint strokePaint, fillPaint;
    if (fill) {
        gc->platformContext()->setupPaintForFilling(&fillPaint);
        setupForTextPainting(&fillPaint, gc->fillColor().rgb());
    }
    if (stroke) {
        gc->platformContext()->setupPaintForStroking(&strokePaint, 0, 0);
        setupForTextPainting(&strokePaint, gc->strokeColor().rgb());
    }

    GlyphBuffer glyphBuffer;
    HarfBuzzShaper shaper(this, run);
    shaper.setDrawRange(from, to);
    if (!shaper.shape(&glyphBuffer))
        return;
    FloatPoint adjustedPoint = shaper.adjustStartPoint(point);
    drawGlyphBuffer(gc, run, glyphBuffer, adjustedPoint);
}
Esempio n. 8
0
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsDevanagariCommonLatinCommon) {
  UChar devanagariCommonLatinString[] = {0x915, 0x94d, 0x930, 0x20,
                                         0x61,  0x62,  0x2E};
  TextRun devanagariCommonLatin(devanagariCommonLatinString, 7);
  HarfBuzzShaper shaper(&font, devanagariCommonLatin);
  RefPtr<ShapeResult> result = shaper.shapeResult();

  ASSERT_EQ(3u, testInfo(result)->numberOfRunsForTesting());
  ASSERT_TRUE(
      testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script));
  EXPECT_EQ(0u, startIndex);
  EXPECT_EQ(1u, numGlyphs);
  EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script);

  ASSERT_TRUE(
      testInfo(result)->runInfoForTesting(1, startIndex, numGlyphs, script));
  EXPECT_EQ(3u, startIndex);
  EXPECT_EQ(1u, numGlyphs);
  EXPECT_EQ(HB_SCRIPT_DEVANAGARI, script);

  ASSERT_TRUE(
      testInfo(result)->runInfoForTesting(2, startIndex, numGlyphs, script));
  EXPECT_EQ(4u, startIndex);
  EXPECT_EQ(3u, numGlyphs);
  EXPECT_EQ(HB_SCRIPT_LATIN, script);
}
Esempio n. 9
0
FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int height, int from, int to) const
{
    HarfBuzzShaper shaper(this, run);
    if (!shaper.shape())
        return FloatRect();
    return shaper.selectionRect(point, height, from, to);
}
Esempio n. 10
0
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
{
    HarfBuzzShaper shaper(this, run);
    if (shaper.shape())
        return shaper.totalWidth();
    LOG_ERROR("Shaper couldn't shape text run.");
    return 0;
}
Esempio n. 11
0
int Font::offsetForPositionForComplexText(const TextRun& run, float x, bool) const
{
    HarfBuzzShaper shaper(this, run);
    if (shaper.shape())
        return shaper.offsetForPosition(x);
    LOG_ERROR("Shaper couldn't shape text run.");
    return 0;
}
Esempio n. 12
0
FloatRect Font::selectionRectForComplexText(const TextRun& run, const FloatPoint& point, int h, int from, int to) const
{
    HarfBuzzShaper shaper(this, run);
    if (shaper.shape())
        return shaper.selectionRect(point, h, from, to);
    LOG_ERROR("Shaper couldn't shape text run.");
    return FloatRect();
}
Esempio n. 13
0
// Return the code point index for the given |x| offset into the text run.
int Font::offsetForPositionForComplexText(const TextRun& run, float xFloat,
                                          bool includePartialGlyphs) const
{
    HarfBuzzShaper shaper(this, run);
    if (!shaper.shape())
        return 0;
    return shaper.offsetForPosition(xFloat);
}
Esempio n. 14
0
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int, int) const
{
    GlyphBuffer glyphBuffer;
    HarfBuzzShaper shaper(this, run);
    if (shaper.shape(&glyphBuffer))
        drawGlyphBuffer(context, run, glyphBuffer, point);
    else
        LOG_ERROR("Shaper couldn't shape glyphBuffer.");
}
Esempio n. 15
0
ade::TensptrT grad_max (ade::iFunctor* fwd, size_t gradidx, ade::TensT tens)
{
	ade::TensptrT fwd_cpy(ade::Functor::get(
		fwd->get_opcode(), fwd->get_children()));
	auto fchildren = fwd->get_children();
	ade::CoordptrT shaper(fchildren[gradidx].get_shaper()->reverse());
	ade::TensptrT rev_fwd(ade::Functor::get(ade::Opcode{"SUM",age::SUM},
		{ade::FuncArg(fwd_cpy, shaper)}));
	return age::eq(rev_fwd, tens[gradidx]);
}
Esempio n. 16
0
int Font::offsetForPositionForComplexText(const TextRun& run, float x, bool includePartialGlyphs) const
{
    if (preferHarfBuzz(this)) {
        HarfBuzzShaper shaper(this, run);
        if (shaper.shape())
            return shaper.offsetForPosition(x);
    }
    ComplexTextController controller(this, run);
    return controller.offsetForPosition(x, includePartialGlyphs);
}
Esempio n. 17
0
// Return the code point index for the given |x| offset into the text run.
int Font::offsetForPositionForComplexText(const TextRun& run, float position, bool) const
{
    // 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 targetX = static_cast<int>(position);

    HarfBuzzShaper shaper(this, run);
    if (!shaper.shape())
        return 0;
    return shaper.offsetForPosition(targetX);
}
Esempio n. 18
0
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsLeadingCommon) {
  TextRun leadingCommon(reinterpret_cast<const LChar*>("... test"), 8);
  HarfBuzzShaper shaper(&font, leadingCommon);
  RefPtr<ShapeResult> result = shaper.shapeResult();

  ASSERT_EQ(1u, testInfo(result)->numberOfRunsForTesting());
  ASSERT_TRUE(
      testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script));
  EXPECT_EQ(0u, startIndex);
  EXPECT_EQ(8u, numGlyphs);
  EXPECT_EQ(HB_SCRIPT_LATIN, script);
}
Esempio n. 19
0
float Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int, int) const
{
    GlyphBuffer glyphBuffer;
    HarfBuzzShaper shaper(this, run);
    if (shaper.shape(&glyphBuffer)) {
        FloatPoint startPoint = point;
        float startX = startPoint.x();
        drawGlyphBuffer(context, run, glyphBuffer, startPoint);
        return startPoint.x() - startX;
    }
    LOG_ERROR("Shaper couldn't shape glyphBuffer.");
    return 0;
}
Esempio n. 20
0
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, IntRectExtent* glyphBounds) const
{
    HarfBuzzShaper shaper(this, run, HarfBuzzShaper::NotForTextEmphasis, fallbackFonts);
    if (!shaper.shape())
        return 0;

    glyphBounds->setTop(floorf(-shaper.glyphBoundingBox().top()));
    glyphBounds->setBottom(ceilf(shaper.glyphBoundingBox().bottom()));
    glyphBounds->setLeft(std::max<int>(0, floorf(-shaper.glyphBoundingBox().left())));
    glyphBounds->setRight(std::max<int>(0, ceilf(shaper.glyphBoundingBox().right() - shaper.totalWidth())));

    return shaper.totalWidth();
}
Esempio n. 21
0
TEST_F(HarfBuzzShaperTest, ResolveCandidateRunsArabic) {
  UChar arabicString[] = {0x628, 0x64A, 0x629};
  TextRun arabic(arabicString, 3);
  HarfBuzzShaper shaper(&font, arabic);
  RefPtr<ShapeResult> result = shaper.shapeResult();

  ASSERT_EQ(1u, testInfo(result)->numberOfRunsForTesting());
  ASSERT_TRUE(
      testInfo(result)->runInfoForTesting(0, startIndex, numGlyphs, script));
  EXPECT_EQ(0u, startIndex);
  EXPECT_EQ(3u, numGlyphs);
  EXPECT_EQ(HB_SCRIPT_ARABIC, script);
}
Esempio n. 22
0
/**
    Use HarfBuzz to shape segment in question
 */
void shapeGlyphs(StoryText *itemText, int startIndex, int endIndex)
{
    if(startIndex < 0 || endIndex < 1) { return; }

    QString text = itemText->text(startIndex, endIndex-startIndex); //this one takes pos, len

    ScText * scitem = itemText->item(startIndex);
    ScFace scface = scitem->font();
    qreal size = scitem->fontSize();
    
    ShaperFontInfo font(scface, size / 10.0);
    ShaperItemInfo shaper(&font);
    ShaperOutput out = shaper.shapeItem(text); //HarfBuzz Magic

    //out.glyphs has our glyphs
    for(uint i = 0; i < out.num_glyphs; i++)
    {
        GlyphLayout &glyph = itemText->item(startIndex + i)->glyph;
        glyph.glyph = out.glyphs[i];

        // XXX: I can't figure out how to use the advances returned by harfbuzz
        //      to position the glyphs, so I'm going to ask the scribus font
        //      class to get the advances for me, then I'll handle marks as
        //      a special case where there's no advance
        //
        //      Please somebody FIXME
        //
        glyph.xadvance = scface.glyphWidth(glyph.glyph, size); //works .. sorta!!

        if(out.attributes[i].mark) //HACK vowel marks
        {
            glyph.xadvance = 0;
        }

        //debugging
        // qDebug() << "glyphs[" << i << "] =" << out.glyphs[i];
        // qDebug() << "advance[" << i << "] =" << out.advances[i];
    }

    if(out.num_glyphs < (uint)text.length())
    {
        // There were some ligatures, so zero-out the extra characters at the end of this run
        for(int i = out.num_glyphs; i < text.length(); i++)
        {
            GlyphLayout &glyph = itemText->item(startIndex + i)->glyph;
            glyph.glyph = scface.char2CMap(QChar::Nbsp);
            glyph.xadvance = 0;
        }

    }
}
Esempio n. 23
0
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
{
    if (!run.length())
        return;

    GlyphBuffer glyphBuffer;
    HarfBuzzShaper shaper(this, run);
    shaper.setDrawRange(from, to);
    if (!shaper.shape(&glyphBuffer))
        return;
    FloatPoint adjustedPoint = shaper.adjustStartPoint(point);

    drawGlyphBuffer(context, run, glyphBuffer, adjustedPoint);
}
Esempio n. 24
0
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>* fallbackFonts, GlyphOverflow* glyphOverflow) const
{
    if (preferHarfBuzz(this)) {
        HarfBuzzShaper shaper(this, run);
        if (shaper.shape())
            return shaper.totalWidth();
    }
    ComplexTextController controller(this, run, true, fallbackFonts);
    if (glyphOverflow) {
        glyphOverflow->top = max<int>(glyphOverflow->top, ceilf(-controller.minGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().ascent()));
        glyphOverflow->bottom = max<int>(glyphOverflow->bottom, ceilf(controller.maxGlyphBoundingBoxY()) - (glyphOverflow->computeBounds ? 0 : fontMetrics().descent()));
        glyphOverflow->left = max<int>(0, ceilf(-controller.minGlyphBoundingBoxX()));
        glyphOverflow->right = max<int>(0, ceilf(controller.maxGlyphBoundingBoxX() - controller.totalWidth()));
    }
    return controller.totalWidth();
}
Esempio n. 25
0
// Tests that runs with zero glyphs (the ZWJ non-printable character in this
// case) are handled correctly. This test passes if it does not cause a crash.
TEST_F(CachingWordShaperTest, SubRunWithZeroGlyphs) {
    // "Foo &zwnj; bar"
    const UChar str[] = {0x46, 0x6F, 0x6F, 0x20, 0x200C,
                         0x20, 0x62, 0x61, 0x71, 0x0
                        };
    TextRun textRun(str, 9);

    CachingWordShaper shaper(cache.get());
    FloatRect glyphBounds;
    ASSERT_GT(shaper.width(&font, textRun, nullptr, &glyphBounds), 0);

    GlyphBuffer glyphBuffer;
    shaper.fillGlyphBuffer(&font, textRun, fallbackFonts, &glyphBuffer, 0, 8);

    shaper.getCharacterRange(&font, textRun, 0, 8);
}
Esempio n. 26
0
void SHAPER::compute(DspBuffer& dspbuf) //final
{
    float pad = _dbd._inputPad;
    int inumframes = dspbuf._numframes;

    float amt = _param[0].eval();//,0.01f,100.0f);
    _fval[0] = amt;

    float* inpbuf = getInpBuf1(dspbuf); 

    //float la = decibel_to_linear_amp_ratio(amt);
    if(1) for( int i=0; i<inumframes; i++ )
    {   float s1 = shaper(inpbuf[i]*pad,amt);
        output1(dspbuf,i, s1 );
    }
}
Esempio n. 27
0
static bool decomposedShaping(FT_Face face, HB_Script script, const QChar &ch)
{
    QString uc = QString().append(ch);
    Shaper shaper(face, script, uc);

    uc = uc.normalized(QString::NormalizationForm_D);
    Shaper decomposed(face, script, uc);

    if( shaper.shaper_item.num_glyphs != decomposed.shaper_item.num_glyphs )
        goto error;

    for (unsigned int i = 0; i < shaper.shaper_item.num_glyphs; ++i) {
        if ((shaper.shaper_item.glyphs[i]&0xffffff) != (decomposed.shaper_item.glyphs[i]&0xffffff))
            goto error;
    }
    return true;
 error:
    QString str = "";
    int i = 0;
    while (i < uc.length()) {
        str += QString("%1 ").arg(uc[i].unicode(), 4, 16);
        ++i;
    }
    qDebug("%s: decomposedShaping of char %4x failed\n    decomposedString: %s\n   nglyphs=%d, decomposed nglyphs %d",
           face->family_name,
           ch.unicode(), str.toLatin1().data(),
           shaper.shaper_item.num_glyphs,
           decomposed.shaper_item.num_glyphs);

    str = "";
    i = 0;
    while (i < shaper.shaper_item.num_glyphs) {
        str += QString("%1 ").arg(shaper.shaper_item.glyphs[i], 4, 16);
        ++i;
    }
    qDebug("    composed glyph result   = %s", str.toLatin1().constData());
    str = "";
    i = 0;
    while (i < decomposed.shaper_item.num_glyphs) {
        str += QString("%1 ").arg(decomposed.shaper_item.glyphs[i], 4, 16);
        ++i;
    }
    qDebug("    decomposed glyph result = %s", str.toLatin1().constData());
    return false;
}
TEST_F(CachingWordShaperTest, GlyphBoundsWithSpaces)
{
    CachingWordShaper shaper(cache.get());

    TextRun periods(reinterpret_cast<const LChar*>(".........."), 10);
    FloatRect periodsGlyphBounds;
    float periodsWidth = shaper.width(&font, periods, nullptr, &periodsGlyphBounds);

    TextRun periodsAndSpaces(reinterpret_cast<const LChar*>(". . . . . . . . . ."), 19);
    FloatRect periodsAndSpacesGlyphBounds;
    float periodsAndSpacesWidth = shaper.width(&font, periodsAndSpaces, nullptr, &periodsAndSpacesGlyphBounds);

    // The total width of periods and spaces should be longer than the width of periods alone.
    ASSERT_GT(periodsAndSpacesWidth, periodsWidth);

    // The glyph bounds of periods and spaces should be longer than the glyph bounds of periods alone.
    ASSERT_GT(periodsAndSpacesGlyphBounds.width(), periodsGlyphBounds.width());
}
void InlineTextBox::characterWidths(Vector<float>& widths) const
{
    FontCachePurgePreventer fontCachePurgePreventer;

    const ComputedStyle& styleToUse = lineLayoutItem().styleRef(isFirstLineStyle());
    const Font& font = styleToUse.font();

    TextRun textRun = constructTextRun(styleToUse, font);

    SimpleShaper shaper(&font, textRun);
    float lastWidth = 0;
    widths.resize(m_len);
    for (unsigned i = 0; i < m_len; i++) {
        shaper.advance(i + 1);
        widths[i] = shaper.runWidthSoFar() - lastWidth;
        lastWidth = shaper.runWidthSoFar();
    }
}
Esempio n. 30
0
// Tests that filling a glyph buffer for a specific range returns the same
// results when shaping word by word as when shaping the full run in one go.
TEST_F(CachingWordShaperTest, CommonAccentLeftToRightFillGlyphBuffer) {
    // "/. ." with an accent mark over the first dot.
    const UChar str[] = {0x2F, 0x301, 0x2E, 0x20, 0x2E, 0x0};
    TextRun textRun(str, 5);

    CachingWordShaper shaper(cache.get());
    GlyphBuffer glyphBuffer;
    shaper.fillGlyphBuffer(&font, textRun, fallbackFonts, &glyphBuffer, 0, 3);

    std::unique_ptr<ShapeCache> referenceCache = wrapUnique(new ShapeCache());
    CachingWordShaper referenceShaper(referenceCache.get());
    GlyphBuffer referenceGlyphBuffer;
    font.setCanShapeWordByWordForTesting(false);
    referenceShaper.fillGlyphBuffer(&font, textRun, fallbackFonts,
                                    &referenceGlyphBuffer, 0, 3);

    ASSERT_EQ(referenceGlyphBuffer.glyphAt(0), glyphBuffer.glyphAt(0));
    ASSERT_EQ(referenceGlyphBuffer.glyphAt(1), glyphBuffer.glyphAt(1));
    ASSERT_EQ(referenceGlyphBuffer.glyphAt(2), glyphBuffer.glyphAt(2));
}