I'm trying to unit test generated svg in batik.
My development machine is windows,
my CI environment is Linux,
I use a a fixture to compare the svg result with my input, thus comparing the generated svg with what I've got in a file in my test/resource folder
I want my environments to be identical, so what I see in my development environment is what I get.
Initially I used the standard monospaced font.
To avoid the problem I tried the following: The documentation on Batik seems to suggest its possible to include the font in the generated svg to make it "self contained". I found out there are 2 options:
include the font definition
render the text themselves as strokes
That does not work either. Rendering takes place on the font definition before inclusion in the svg. I found there's a difference: java uses the system (windows/linux) font rendering to determine the font definition. They work differently. There are some articles on that topic.
But why render if you use monospaced fonts? The result should be the same, right? In the case of svg, I really would like to delegate rendering to the platform (browser or other tool) interpreting the svg.
My code:
DOMImplementation domImpl = GenericDOMImplementation.getDOMImplementation();
// Create an instance of org.w3c.dom.Document.
Document document = domImpl.createDocument( "http://www.w3.org/2000/svg", "svg", null );
// embed fonts in svg document
SVGGeneratorContext ctx = SVGGeneratorContext.createDefault( document );
ctx.setEmbeddedFontsOn( true );
GraphicsEnvironment ge;
try {
ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
ge.registerFont( Font.createFont( Font.TRUETYPE_FONT, this.getClass().getResourceAsStream( "/font/VeraMono.ttf" ) ) );
}
catch ( FontFormatException | IOException e ) {
LOG.error( "Cannot load font!", e );
}
// Create an instance of the SVG Generator: true converts text to paths.
SVGGraphics2D g2 = new SVGGraphics2D( ctx, true );
g2.setFont( new Font( "VeraMono", Font.PLAIN, 20 ) );
g2.drawString( "example text", 5, 30 );
Related
I tried to generate pdf files with libharu. There are many different languages input in my case, so I chose the encoder(UTF-8). The following architecture is about my code:
HPDF_UseUTFEncodings(pdf);
HPDF_SetCurrentEncoder(pdf, "UTF-8");
const char * font_name = HPDF_LoadTTFontFromFile(pdf, "ArialUnicodeMS.ttf", HPDF_TRUE);
HPDF_Font font = HPDF_GetFont(pdf, font_name, "UTF-8");
HPDF_Page_SetFontAndSize(page, font, 12);
HPDF_Page_BeginText(page);
HPDF_Page_MoveTextPos(page, 60 + i * 100, height - 75);
HPDF_Page_ShowText(page, font_name[i]);
HPDF_Page_EndText(page);
Here are my testing input: "тест", "テスト", "Ölçek", "ทดสอบ", "테스트", "測試", "测试". The library worked, but not in every fonts. I know I shoud use the font support UTF-8, so I have tried ArialUnicodeMS, DroidSans, DroidSansFallback, DroidSansFallbackFull. Only ArialUnicodeMS can output all inputs. I use FontForge to check the difference between these fonts, but DroidSans also povides characters I want. Please tell me the reason about this situation, thanks a lot.
Below was Blank App (C++/WinRT) project.
I am trying to create a TextBlock and set its Text (x,y) property "Left" and "Top" dynamically from MainPage.cpp and display it on runtime XAML form.
However, for testing, code below able to compile successfully and at the runtime result, no TextBlock component "Hellow World!" is shown.
Is there anything wrong or missing ?
namespace winrt::...::implementation
{
MainPage::MainPage()
{
InitializeComponent();
Process();
}
void MainPage::Process()
{
winrt::hstring hs = L"Hello World!";
TextBlock tbx;
tbx.FontFamily( Windows::UI::Xaml::Media::FontFamily(
L"Segoe UI Semibold" ) );
tbx.FontSize(72.0);
tbx.Foreground( SolidColorBrush( Colors::Orange() ) );
tbx.VerticalAlignment( VerticalAlignment::Center );
tbx.TextAlignment( TextAlignment::Center );
tbx.Text( hs );
Window window = Window::Current();
window.Content( tbx );
window.Activate();
}
}
Please advise.
The underlying problem is a XAML layout issue. Here's a little demo that should put you on the right track. I modified your MainPage above to look like this:
MainPage::MainPage()
{
InitializeComponent();
winrt::hstring hs = L"Hello World!";
TextBlock tbx;
tbx.FontFamily(Windows::UI::Xaml::Media::FontFamily(
L"Segoe UI Semibold"));
tbx.FontSize(72.0);
tbx.Foreground(SolidColorBrush(Colors::Orange()));
tbx.VerticalAlignment(VerticalAlignment::Center);
tbx.TextAlignment(TextAlignment::Center);
tbx.Text(hs);
this->Content().as<Panel>().Children().Append(tbx);
}
The XAML page looks like this:
<Page ... >
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center">
<Button x:Name="myButton" >Click Me</Button>
</StackPanel>
</Page>
The basic idea is that you want to add the control to a panel that is managing layout on the main page, rather than adding it to the top level Window object. It may be instructive to play around in the designer a bit to get the desired look, then restructure it into equivalent code using C++ /WinRT.
Ben
Just discovered this works:
TranslateTransform pos;
pos.X( 500 );
pos.Y( 500 );
tbx.RenderTransform( pos )
Alternatively, found a latest video from Microsoft Build 2019, it shown a sample of UWP C++ with XAML with related info within.
Here is the link:
Meet C++/WinRT 2.0: Faster and smarter in the open - BRK4009
[https://www.youtube.com/watch?v=X41j_gzSwOY][1]
I'm using ember-emojione to display and insert emoji.
Out of four rendering options that EmojiOne offers:
PNG sprites
PNG individual images
SVG sprites
SVG individual images
...only PNG sprites suit me. Individual images take too much time to load and emoji display sequentially. SVG sprites are awesome, but rerendering the preview area causes SVG sprite emoji to flicker. Only PNG sprite emoji never flicker and display simultaneously.
Unfortunately, EmojiOne offers spritesheets only in three sizes: 64, 128 and 512 px. We need to display emoji in 20 px size.
Resizing emoji displayed via PNG sprites is problematic.
ember-emojione readme suggests this hack to resize PNG sprite emoji:
.emojione {
transform: scale(0.3125);
margin: -22px;
}
It works, but it has some disadvantages:
In certain cases, emoji appear blurred.
Text selection blows up:
The solution is to use emoji spritesheets tailored to desired size. The Deveo/emojione-png-sprites repo offers such spritesheets.
But when I include those spritesheets instead of default ones, ember-emojione emoji picker component displays incorrectly.
Question: how do I use ember-emojione with emojione-png-sprites correctly?
emojione-png-sprites relies on Sass mixins, so you'll need ember-cli-sass. If you don't want to install ember-cli-sass, you can alternatively precompile mixin invocations manually and insert resulting CSS into your app.
Decide which spritesheets to include from emojione-png-sprites.
We're gonna use 20px emoji. For retina, we'll also need double and triple size spritesheets. As 40px and 60px aren't available, we're gonna use next available ones: 48px and 64px.
Include spritesheets and the Sass file into your repo. Run these commands in your Ember app root:
bower i -S emojione-png-sprite-20=https://raw.githubusercontent.com/Deveo/emojione-png-sprites/v0.3.0/dist/sprite-20.png
bower i -S emojione-png-sprite-48=https://raw.githubusercontent.com/Deveo/emojione-png-sprites/v0.3.0/dist/sprite-48.png
bower i -S emojione-png-sprite-64=https://raw.githubusercontent.com/Deveo/emojione-png-sprites/v0.3.0/dist/sprite-64.png
bower i -S emojione-png-sprite-style=https://raw.githubusercontent.com/Deveo/emojione-png-sprites/v0.3.01/dist/style.scss
It's very important that you use a specific release version of the files, so that your dependencies are locked. Otherwise, if the repo has a breaking change, an innocent bower install will break your project.
Tell ember-emojione not to include default EmojiOne CSS and spritesheets. In your app's ember-cli-build.js:
module.exports = function (defaults) {
var app = new EmberApp(defaults, {
"ember-emojione": {
shouldImportCss: false,
shouldIncludePngSprite: false,
shouldIncludeSvgSprite: false,
shouldIncludePngImages: false,
shouldIncludeSvgImages: false
}
});
// ...
Import PNG sprites into your app.
Install broccoli-funnel:
npm install -D broccoli-funnel
In your app's ember-cli-build.js:
var Funnel = require("broccoli-funnel");
module.exports = function (defaults) {
var app = new EmberApp(defaults, {
// ...
}
});
const funnels = [
// PNG sprites
new Funnel(app.bowerDirectory + "/emojione-png-sprite-20", {
include: ['index.png'],
getDestinationPath () {
return "assets/emojione-png-sprites/sprite-20.png";
}
}),
new Funnel(app.bowerDirectory + "/emojione-png-sprite-48", {
include: ['index.png'],
getDestinationPath () {
return "assets/emojione-png-sprites/sprite-48.png";
}
}),
new Funnel(app.bowerDirectory + "/emojione-png-sprite-64", {
include: ['index.png'],
getDestinationPath () {
return "assets/emojione-png-sprites/sprite-64.png";
}
}),
];
if (app.env === "development" || app.env === "test") {
app.import(app.bowerDirectory + "/timekeeper/lib/timekeeper.js");
}
return app.toTree(funnels);
};
In your app's Sass, include the mixin and invoke it:
#import "bower_components/emojione-png-sprite-style/index.scss";
#include sprity-emojione(20, "/assets/emojione-png-sprites", (2: 48, 3: 64));
This will break the looks of ember-emojione components. The addon contains a mixin that restores the looks:
#import 'node_modules/ember-emojione/app/styles/ember-emojione';
#include ember-emojione-cancel-scale;
I want to set the line spacing of a QTextEdit.
It's no problem to get that information with
QFontMetrics::lineSpacing();
But how to set that?
I tried with StyleSheets, but that didn't work:
this->setStyleSheet("QTextEdit{ height: 200%; }");
or
this->setStyleSheet("QTextEdit{ line-height: 200%; }");
Partial solution:
Well, I've found a solution - not the way I wanted it, but at least it's simple and it gives nearly my intended behavior, enough for my proof of concept.
On every new line there's some linespacing. But if you just type until the text is automatically wrapped to a new line you wont have line-spacing between this two lines. This hack only works with text blocks, see the code.
Just keep in mind it's brute force and a ugly hack. But it provides some kind of line-spacing to your beautiful QTextEdit. Call it everytime your text changes.
void setLineSpacing(int lineSpacing) {
int lineCount = 0;
for (QTextBlock block = this->document()->begin(); block.isValid();
block = block.next(), ++lineCount) {
QTextCursor tc = QTextCursor(block);
QTextBlockFormat fmt = block.blockFormat();
if (fmt.topMargin() != lineSpacing
|| fmt.bottomMargin() != lineSpacing) {
fmt.setTopMargin(lineSpacing);
//fmt.setBottomMargin(lineSpacing);
tc.setBlockFormat(fmt);
}
}
}
The QFontMetrics contains (per the name) static properties that come from the font file. How wide a capital "C" is, etc. lineSpacing() gets you the natural distance in single-spacing that the person who designed the font encoded into the font itself. If you actually wanted to change that (you don't)...the somewhat complicated story of how is told here:
http://fontforge.sourceforge.net/faq.html#linespace
As for the line spacing in a QTextEdit...it looks (to me) like that is seen as one of the things that falls under Qt's extensibility model for specifying text "layouts":
http://doc.qt.io/qt-4.8/richtext-layouts.html
You would supply your own layout class to the QTextDocument instead of using the default. Someone tried it here but did not post their completed code:
http://www.qtcentre.org/threads/4198-QTextEdit-with-custom-space-between-lines
I know this is an old question, but I've spent a lot of time today trying to solve this for PyQt5 5.15.2. I'm posting my solution in case it is useful to others. The solution is for Python, but should be easily transferable.
The following code will change the line height to 150% for a populated QTextEdit widget in one go. Further editing will pick up the current block format, and continue applying it. I've found it to be very slow for large documents though.
textEdit = QTextEdit()
# ... load text into widget here ...
blockFmt = QTextBlockFormat()
blockFmt.setLineHeight(150, QTextBlockFormat.ProportionalHeight)
theCursor = textEdit.textCursor()
theCursor.clearSelection()
theCursor.select(QTextCursor.Document)
theCursor.mergeBlockFormat(blockFmt)
Applying blockformat to entire document rather than each line works.
QTextBlockFormat bf = this->textCursor().blockFormat();
bf.setLineHeight(lineSpacing, QTextBlockFormat::LineDistanceHeight) ;
this->textCursor().setBlockFormat(bf);
I have translated Jadzia626's code to C++ and it works. Here is the information about setLineHeight()
qreal lineSpacing = 35;
QTextCursor textCursor = ui->textBrowser->textCursor();
QTextBlockFormat * newFormat = new QTextBlockFormat();
textCursor.clearSelection();
textCursor.select(QTextCursor::Document);
newFormat->setLineHeight(lineSpacing, QTextBlockFormat::ProportionalHeight);
textCursor.setBlockFormat(*newFormat);
I tried setting all possible styles to something other than grey, just to try and get rid of the grey overlay as shown in the "Hello item 1" in the attached image of a list. Nothing worked. I examined the ListSkin class too and didn't fins anything that would draw these. How to get rid of these overlays?
<s:List id="list" width="100%" height="100%"
dataProvider="{dp}"
focusAlpha="0"
contentBackgroundAlpha="0"
contentBackgroundColor="0xFFFFFF"
selectionColor="0xFFFFFF"
downColor="0xFFFFFF"
borderVisible="false"
>
</s:List>
I just helped a client with this same thing. You, basically, have to extend the LabelItemRemderer class to not draw the rectangle. It is not exposed via styles or colors for you to change.
Look at this code (Starting at line 853 in the LabelItemRemderer):
// Selected and down states have a gradient overlay as well
// as different separators colors/alphas
if (selected || down)
{
var colors:Array = [0x000000, 0x000000 ];
var alphas:Array = [.2, .1];
var ratios:Array = [0, 255];
var matrix:Matrix = new Matrix();
// gradient overlay
matrix.createGradientBox(unscaledWidth, unscaledHeight, Math.PI / 2, 0, 0 );
graphics.beginGradientFill(GradientType.LINEAR, colors, alphas, ratios, matrix);
graphics.drawRect(0, 0, unscaledWidth, unscaledHeight);
graphics.endFill();
}
You basically need some way to force this code to not run. You can do this by creating your own itemRenderer from scratch. Or you can extend the LabelItemRenderer, override the drawBackground() method and copy all the parent drawBackground() code into your extended child; minus the block above.
I'd love to see the color exposed as a style or something. I'd love to see a magic property (or style) we could use to make the overlay vanish altogether. Feel free to log this as a bug into the Apache Flex Jira.