Esempio n. 1
0
void InlineListWidget::updateGeometry()
{
    FR_PushAttrib();
    FR_SetFont(page().predefinedFont(mn_page_fontid_t(font())));
    Size2Raw maxSize{};
    Size2Raw size;
    for (int i = 0; i < items().size(); ++i)
    {
        FR_TextSize(&size, items().at(i)->text().toUtf8().constData());
        maxSize.width = de::max(maxSize.width, size.width);
        maxSize.height = de::max(maxSize.height, size.height);
    }
    geometry().setSize(Vector2ui(maxSize.width, maxSize.height));
    FR_PopAttrib();
}
Esempio n. 2
0
void LabelWidget::updateGeometry()
{
    /// @todo What if patch replacement is disabled?
    if(d->patch)
    {
        patchinfo_t info;
        R_GetPatchInfo(*d->patch, &info);
        geometry().setSize(Vector2ui(info.geometry.size.width, info.geometry.size.height));
        return;
    }

    FR_PushAttrib();
    Size2Raw size;
    FR_SetFont(page().predefinedFont(mn_page_fontid_t(font())));
    FR_TextSize(&size, d->text.toUtf8().constData());
    geometry().setSize(Vector2ui(size.width, size.height));
    FR_PopAttrib();
}
Esempio n. 3
0
void FR_DrawText3(const char* text, const Point2Raw* _origin, int alignFlags, short _textFlags)
{
    fontid_t origFont = FR_Font();
    float cx, cy, extraScale;
    drawtextstate_t state;
    const char* fragment;
    int pass, curCase;
    Point2Raw origin;
    Size2Raw textSize;
    size_t charCount;
    float origColor[4];
    char* str, *end;
    boolean escaped = false;

    errorIfNotInited("FR_DrawText");

    if(!text || !text[0]) return;

    origin.x = _origin? _origin->x : 0;
    origin.y = _origin? _origin->y : 0;

    _textFlags &= ~(DTF_INTERNAL_MASK);

    // If we aren't aligning to top-left we need to know the dimensions.
    if(alignFlags & ALIGN_RIGHT)
        FR_TextSize(&textSize, text);

    DENG_ASSERT_IN_MAIN_THREAD();
    DENG_ASSERT_GL_CONTEXT_ACTIVE();

    // We need to change the current color, so remember for restore.
    glGetFloatv(GL_CURRENT_COLOR, origColor);

    for(pass = ((_textFlags & DTF_NO_SHADOW)  != 0? 1 : 0);
        pass < ((_textFlags & DTF_NO_GLITTER) != 0? 2 : 3); ++pass)
    {
        short textFlags = 0;

        // Configure the next pass.
        cx = (float) origin.x;
        cy = (float) origin.y;
        curCase = -1;
        charCount = 0;
        switch(pass)
        {
        case 0: textFlags = _textFlags | (DTF_NO_GLITTER|DTF_NO_CHARACTER); break;
        case 1: textFlags = _textFlags | (DTF_NO_SHADOW |DTF_NO_GLITTER);   break;
        case 2: textFlags = _textFlags | (DTF_NO_SHADOW |DTF_NO_CHARACTER); break;
        }

        // Apply defaults.
        initDrawTextState(&state, textFlags);

        str = (char*)text;
        while(*str)
        {
            if(*str == FR_FORMAT_ESCAPE_CHAR)
            {
                escaped = true;
                ++str;
                continue;
            }
            if(!escaped && *str == '{') // Paramaters included?
            {
                fontid_t lastFont = state.fontNum;
                int lastTracking = state.tracking;
                float lastLeading = state.leading;
                float lastShadowStrength = state.shadowStrength;
                float lastGlitterStrength = state.glitterStrength;
                boolean lastCaseScale = state.caseScale;
                float lastRGBA[4];
                int numBreaks = 0;

                lastRGBA[CR] = state.rgba[CR];
                lastRGBA[CG] = state.rgba[CG];
                lastRGBA[CB] = state.rgba[CB];
                lastRGBA[CA] = state.rgba[CA];

                parseParamaterBlock(&str, &state, &numBreaks);

                if(numBreaks != 0)
                {
                    do
                    {
                        cx = (float) origin.x;
                        cy += state.lastLineHeight * (1+lastLeading);
                    } while(--numBreaks > 0);
                }

                if(state.fontNum != lastFont)
                    FR_SetFont(state.fontNum);
                if(state.tracking != lastTracking)
                    FR_SetTracking(state.tracking);
                if(state.leading != lastLeading)
                    FR_SetLeading(state.leading);
                if(state.rgba[CR] != lastRGBA[CR] || state.rgba[CG] != lastRGBA[CG] || state.rgba[CB] != lastRGBA[CB] || state.rgba[CA] != lastRGBA[CA])
                    FR_SetColorAndAlphav(state.rgba);
                if(state.shadowStrength != lastShadowStrength)
                    FR_SetShadowStrength(state.shadowStrength);
                if(state.glitterStrength != lastGlitterStrength)
                    FR_SetGlitterStrength(state.glitterStrength);
                if(state.caseScale != lastCaseScale)
                    FR_SetCaseScale(state.caseScale);
            }

            for(end = str; *end && *end != FR_FORMAT_ESCAPE_CHAR && (escaped || *end != '{');)
            {
                int newlines = 0, fragmentAlignFlags;
                float alignx = 0;

                // Find the end of the next fragment.
                if(FR_CaseScale())
                {
                    curCase = -1;
                    // Select a substring with characters of the same case (or whitespace).
                    for(; *end && *end != FR_FORMAT_ESCAPE_CHAR && (escaped || *end != '{') &&
                        *end != '\n'; end++)
                    {
                        escaped = false;

                        // We can skip whitespace.
                        if(isspace(*end))
                            continue;

                        if(curCase < 0)
                            curCase = (isupper(*end) != 0);
                        else if(curCase != (isupper(*end) != 0))
                            break;
                    }
                }
                else
                {
                    curCase = 0;
                    for(; *end && *end != FR_FORMAT_ESCAPE_CHAR && (escaped || *end != '{') &&
                        *end != '\n'; end++) { escaped = false; }
                }

                // No longer escaped.
                escaped = false;

                { char* buffer = enlargeTextBuffer(end - str);
                memcpy(buffer, str, end - str);
                buffer[end - str] = '\0';
                fragment = buffer;
                }

                while(*end == '\n')
                {
                    newlines++;
                    end++;
                }

                // Continue from here.
                str = end;

                if(!(alignFlags & (ALIGN_LEFT|ALIGN_RIGHT)))
                {
                    fragmentAlignFlags = alignFlags;
                }
                else
                {
                    // We'll take care of horizontal positioning of the fragment so align left.
                    fragmentAlignFlags = (alignFlags & ~(ALIGN_RIGHT)) | ALIGN_LEFT;
                    if(alignFlags & ALIGN_RIGHT)
                        alignx = -textSize.width * state.scaleX;
                }

                // Setup the scaling.
                glMatrixMode(GL_MODELVIEW);
                glPushMatrix();

                // Rotate.
                if(state.angle != 0)
                {
                    // The origin is the specified (x,y) for the patch.
                    // We'll undo the aspect ratio (otherwise the result would be skewed).
                    /// @todo Do not assume the aspect ratio and therefore whether
                    // correction is even needed.
                    glTranslatef((float)origin.x, (float)origin.y, 0);
                    glScalef(1, 200.0f / 240.0f, 1);
                    glRotatef(state.angle, 0, 0, 1);
                    glScalef(1, 240.0f / 200.0f, 1);
                    glTranslatef(-(float)origin.x, -(float)origin.y, 0);
                }

                glTranslatef(cx + state.offX + alignx, cy + state.offY + (FR_CaseScale() ? state.caseMod[curCase].offset : 0), 0);
                extraScale = (FR_CaseScale() ? state.caseMod[curCase].scale : 1);
                glScalef(state.scaleX, state.scaleY * extraScale, 1);

                // Draw it.
                if(fr.fontNum)
                {
                    textFragmentDrawer(fragment, 0, 0, fragmentAlignFlags, textFlags, state.typeIn ? (int) charCount : DEFAULT_INITIALCOUNT);
                }
                charCount += strlen(fragment);

                // Advance the current position?
                if(newlines == 0)
                {
                    cx += ((float) textFragmentWidth(fragment) + currentAttribs()->tracking) * state.scaleX;
                }
                else
                {
                    if(strlen(fragment) > 0)
                        state.lastLineHeight = textFragmentHeight(fragment);

                    cx = (float) origin.x;
                    cy += newlines * (float) state.lastLineHeight * (1+FR_Leading());
                }

                glMatrixMode(GL_MODELVIEW);
                glPopMatrix();
            }
        }

        FR_PopAttrib();
    }

    freeTextBuffer();

    FR_SetFont(origFont);
    glColor4fv(origColor);
}