cinder / Cinder

Cinder is a community-developed, free and open source library for professional-quality creative coding in C++.
http://libcinder.org
Other
5.3k stars 940 forks source link

TextLayout formatting inconsistent between OS X + Windows #416

Open lucasvickers opened 10 years ago

lucasvickers commented 10 years ago

I am relying on the TextLayout to provide left aligned text. My expectation is that the first pixel of text would be at the left most border of the returned texture.

1) I don't see this expectation fully met on OS X or on Windows. Is it possible to have TextLayout function in this manner? I was previously using gl::drawstring, but with the typeface I was using it was not rendering special characters. I was able to get Cairo to render the correct characters but Cairo comes with it's own set of complications.

2) I see some pretty drastic spacing inconsistencies between OS X + Windows, which is causing me some headaches in laying out designs.

Please let me know your thoughts. I noticed this on the Dev/Master windows branches.

Thanks

Windows Layout windows-dev

OS X Layout screen shot 2014-03-25 at 5 10 00 pm

Code:

#include "cinder/app/AppNative.h"
#include "cinder/gl/gl.h"
#include "cinder/gl/Texture.h"
#include "cinder/Text.h"

using namespace ci;
using namespace ci::app;
using namespace std;

class CinderProjectApp : public AppNative {
public:
    void setup();
    void mouseDown( MouseEvent event );
    void update();
    void draw();

    gl::Texture smallArial;
    gl::Texture largeArial;
    gl::Texture mediumTNR;
};

void CinderProjectApp::setup()
{
    ColorAf white(1,1,1,1);
    TextLayout tl;

    tl = TextLayout();
    tl.clear( ColorA( 0, 0, 0, 0 ) );
    tl.setFont( Font( "Arial", 20 ));
    tl.setColor( white );
    tl.addLine("Small Text");
    smallArial = tl.render(true);

    tl = TextLayout();
    tl.clear( ColorA( 0, 0, 0, 0 ) );
    tl.setFont( Font( "Arial", 200 ));
    tl.setColor( white );
    tl.addLine("Large Text");
    largeArial = tl.render(true);

    tl = TextLayout();
    tl.clear( ColorA( 0, 0, 0, 0 ) );
    tl.setFont( Font( "Times New Roman", 120 ));
    tl.setColor( white );
    tl.addLine("Medium Text");
    mediumTNR = tl.render(true);

    getWindow()->setSize(1000, 500);

}

void CinderProjectApp::mouseDown( MouseEvent event )
{
}

void CinderProjectApp::update()
{
}

void CinderProjectApp::draw()
{
    // clear out the window with black
    gl::clear( Color( 0, 0, 0 ) );

    gl::color(1,1,1);
    gl::pushMatrices();

    gl::translate(Vec2f(100, 10));
    gl::draw(smallArial);
    gl::drawStrokedRect(smallArial.getBounds());

    gl::translate(Vec2f(0, 10 + smallArial.getHeight()));
    gl::draw(largeArial);
    gl::drawStrokedRect(largeArial.getBounds());

    gl::translate(Vec2f(0, 10 + largeArial.getHeight()));
    gl::draw(mediumTNR);
    gl::drawStrokedRect(mediumTNR.getBounds());

    gl::popMatrices();

}

CINDER_APP_NATIVE( CinderProjectApp, RendererGl )
benjaminbojko commented 8 years ago

Remembered seeing this questions a while back and I was facing the same issue. There is a way to resolve this by using Gdiplus::StringFormat::GenericTypographic() instead of the default gdi+ format. From https://support.microsoft.com/en-us/kb/307208:

The default action of DrawString works against you when you display adjacent runs: First, the default StringFormat object adds an extra 1/6 em at each end of each output; second, when grid fitted widths are less than designed, the rendered string is allowed to contract from its measured size by up to an em.

To avoid these problems, do the following: Always pass MeasureString and DrawString a StringFormat object based on the typographic StringFormat (GenericTypographic).

-and-

Set TextRenderingHint graphics to TextRenderingHintAntiAlias.

Since the code for that is private to TextLayout, I don't know of any way to use the current APIs to fix this w/o going into TextLayout.cpp itself.

colinbouvry commented 7 years ago

Too much space above the text compared to the bottom ! I have difficult to center texture independtly of size !

I tryed Gdiplus::StringFormat::GenericTypographic() but nothing !

Perhaps the solution is to crop to transparency ?