Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  Justifier.cpp

  Sprache: C
 

// SPDX-License-Identifier: MIT OR MPL-2.0 OR LGPL-2.1-or-later OR GPL-2.0-or-later
// Copyright 2012, SIL International, All rights reserved.


#include "inc/Segment.h"
#include "graphite2/Font.h"
#include "inc/debug.h"
#include "inc/CharInfo.h"
#include "inc/Slot.h"
#include "inc/Main.h"
#include <cmath>

using namespace graphite2;

class JustifyTotal {
public:
    JustifyTotal() : m_numGlyphs(0), m_tStretch(0), m_tShrink(0), m_tStep(0), m_tWeight(0{}
    void accumulate(Slot *s, Segment *seg, int level);
    int weight() const { return m_tWeight; }

    CLASS_NEW_DELETE

private:
    int m_numGlyphs;
    int m_tStretch;
    int m_tShrink;
    int m_tStep;
    int m_tWeight;
};

void JustifyTotal::accumulate(Slot *s, Segment *seg, int level)
{
    ++m_numGlyphs;
    m_tStretch += s->getJustify(seg, level, 0);
    m_tShrink += s->getJustify(seg, level, 1);
    m_tStep += s->getJustify(seg, level, 2);
    m_tWeight += s->getJustify(seg, level, 3);
}

float Segment::justify(Slot *pSlot, const Font *font, float width, GR_MAYBE_UNUSED justFlags jflags, Slot *pFirst, Slot *pLast)
{
    Slot *end = last();
    float currWidth = 0.0;
    const float scale = font ? font->scale() : 1.0f;
    Position res;

    if (width < 0 && !(silf()->flags()))
        return width;

    if ((m_dir & 1) != m_silf->dir() && m_silf->bidiPass() != m_silf->numPasses())
    {
        reverseSlots();
        std::swap(pFirst, pLast);
    }
    if (!pFirst) pFirst = pSlot;
    while (!pFirst->isBase()) pFirst = pFirst->attachedTo();
    if (!pLast) pLast = last();
    while (!pLast->isBase()) pLast = pLast->attachedTo();
    const float base = pFirst->origin().x / scale;
    width = width / scale;
    if ((jflags & gr_justEndInline) == 0)
    {
        while (pLast != pFirst && pLast)
        {
            Rect bbox = theGlyphBBoxTemporary(pLast->glyph());
            if (bbox.bl.x != 0.f || bbox.bl.y != 0.f || bbox.tr.x != 0.f || bbox.tr.y == 0.f)
                break;
            pLast = pLast->prev();
        }
    }

    if (pLast)
        end = pLast->nextSibling();
    if (pFirst)
        pFirst = pFirst->nextSibling();

    int icount = 0;
    int numLevels = silf()->numJustLevels();
    if (!numLevels)
    {
        for (Slot *s = pSlot; s && s != end; s = s->nextSibling())
        {
            CharInfo *c = charinfo(s->before());
            if (isWhitespace(c->unicodeChar()))
            {
                s->setJustify(this, 031);
                s->setJustify(this, 021);
                s->setJustify(this, 00, -1);
                ++icount;
            }
        }
        if (!icount)
        {
            for (Slot *s = pSlot; s && s != end; s = s->nextSibling())
            {
                s->setJustify(this, 031);
                s->setJustify(this, 021);
                s->setJustify(this, 00, -1);
            }
        }
        ++numLevels;
    }

    Vector<JustifyTotal> stats(numLevels);
    for (Slot *s = pFirst; s && s != end; s = s->nextSibling())
    {
        float w = s->origin().x / scale + s->advance() - base;
        if (w > currWidth) currWidth = w;
        for (int j = 0; j < numLevels; ++j)
            stats[j].accumulate(s, this, j);
        s->just(0);
    }

    for (int i = (width < 0.0f) ? -1 : numLevels - 1; i >= 0; --i)
    {
        float diff;
        float error = 0.;
        float diffpw;
        int tWeight = stats[i].weight();
        if (tWeight == 0continue;

        do {
            error = 0.;
            diff = width - currWidth;
            diffpw = diff / tWeight;
            tWeight = 0;
            for (Slot *s = pFirst; s && s != end; s = s->nextSibling()) // don't include final glyph
            {
                int w = s->getJustify(this, i, 3);
                float pref = diffpw * w + error;
                int step = s->getJustify(this, i, 2);
                if (!step) step = 1;        // handle lazy font developers
                if (pref > 0)
                {
                    float max = uint16(s->getJustify(this, i, 0));
                    if (i == 0) max -= s->just();
                    if (pref > max) pref = max;
                    else tWeight += w;
                }
                else
                {
                    float max = uint16(s->getJustify(this, i, 1));
                    if (i == 0) max += s->just();
                    if (-pref > max) pref = -max;
                    else tWeight += w;
                }
                int actual = int(pref / step) * step;

                if (actual)
                {
                    error += diffpw * w - actual;
                    if (i == 0)
                        s->just(s->just() + actual);
                    else
                        s->setJustify(this, i, 4, actual);
                }
            }
            currWidth += diff - error;
        } while (i == 0 && int(std::abs(error)) > 0 && tWeight);
    }

    Slot *oldFirst = m_first;
    Slot *oldLast = m_last;
    if (silf()->flags() & 1)
    {
        m_first = pSlot = addLineEnd(pSlot);
        m_last = pLast = addLineEnd(end);
        if (!m_first || !m_last) return -1.0;
    }
    else
    {
        m_first = pSlot;
        m_last = pLast;
    }

    // run justification passes here
#if !defined GRAPHITE2_NTRACING
    json * const dbgout = m_face->logger();
    if (dbgout)
        *dbgout << json::object
                    << "justifies"  << objectid(this)
                    << "passes"     << json::array;
#endif

    if (m_silf->justificationPass() != m_silf->positionPass() && (width >= 0.f || (silf()->flags() &&nbsp;1)))
        m_silf->runGraphite(this, m_silf->justificationPass(), m_silf->positionPass());

#if !defined GRAPHITE2_NTRACING
    if (dbgout)
    {
        *dbgout     << json::item << json::close; // Close up the passes array
        positionSlots(NULL, pSlot, pLast, m_dir);
        Slot *lEnd = pLast->nextSibling();
        *dbgout << "output" << json::array;
        for(Slot * t = pSlot; t != lEnd; t = t->next())
            *dbgout     << dslot(this, t);
        *dbgout         << json::close << json::close;
    }
#endif

    res = positionSlots(font, pSlot, pLast, m_dir);

    if (silf()->flags() & 1)
    {
        if (m_first)
            delLineEnd(m_first);
        if (m_last)
            delLineEnd(m_last);
    }
    m_first = oldFirst;
    m_last = oldLast;

    if ((m_dir & 1) != m_silf->dir() && m_silf->bidiPass() != m_silf->numPasses())
        reverseSlots();
    return res.x;
}

Slot *Segment::addLineEnd(Slot *nSlot)
{
    Slot *eSlot = newSlot();
    if (!eSlot) return NULL;
    const uint16 gid = silf()->endLineGlyphid();
    const GlyphFace * theGlyph = m_face->glyphs().glyphSafe(gid);
    eSlot->setGlyph(this, gid, theGlyph);
    if (nSlot)
    {
        eSlot->next(nSlot);
        eSlot->prev(nSlot->prev());
        nSlot->prev(eSlot);
        eSlot->before(nSlot->before());
        if (eSlot->prev())
            eSlot->after(eSlot->prev()->after());
        else
            eSlot->after(nSlot->before());
    }
    else
    {
        nSlot = m_last;
        eSlot->prev(nSlot);
        nSlot->next(eSlot);
        eSlot->after(eSlot->prev()->after());
        eSlot->before(nSlot->after());
    }
    return eSlot;
}

void Segment::delLineEnd(Slot *s)
{
    Slot *nSlot = s->next();
    if (nSlot)
    {
        nSlot->prev(s->prev());
        if (s->prev())
            s->prev()->next(nSlot);
    }
    else
        s->prev()->next(NULL);
    freeSlot(s);
}

Messung V0.5 in Prozent
C=90 H=96 G=93

¤ Dauer der Verarbeitung: 0.5 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover

NIST Cobol Testsuite

Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=141584
#Domains=738142