Setting QTextDocument painter's rectangle (where to paint) - html

I am painting on a window simple html using QTextDocument::drawContents(painter)
I want to do the drawing inside some margins in the window but I don't see a direct way to specify the target rectangle of the painting (in the painter/window).
I guess a few ways to do it:
Using the QTextDocuments::setMargin (although this does not allow different values for left/top.
Placing the html into an styled <div>
Applying a translation transform to the painter.
But all this seems a bit too much for what I want to do and I guess if I a missing something straight (as you do with QPainter::drawText where you tell the target rectangle)

Set the textWidth property to the width of the area where the text is supposed to fit. The clipping rectangle you pass to drawContents will cut the text off vertically if there's too much of it to fit; you can't do much about that of course.
So, this would be the missing function you're after:
void drawContents(QPainter * p, QTextDocument & doc, const QRectF & rect) {
p->save();
p->translate(rect.topLeft());
doc.setTextWidth(rect.width());
doc.drawContents(p, rect);
p->restore();
}
Yes, you do need to jump through a few hoops, that's why it needs to be factored out. It's perhaps lamentable that a similar overload of drawContents doesn't exist.

Related

Can I change LibGDX Label lineHeight temporarily?

I have a bitmap font built with Hiero, which I'm using in scene2d Labels.
In a single Label instance I need to reduce the font's lineHeight value, but I'd like to leave the other Labels (which are using the same font) intact, so they should keep the default lineHeight of the font.
I've tried to simply adjust the value like this:
label.getStyle().font.getData().setLineHeight(localReducedValue);
However, this has modified all the Labels everywhere -- which, in retrospect, seems logical, since I'm modifying the LabelStyle itself.
Unfortunately something like label.setLineHeight(localReducedValue) doesn't exist, so at this point I see two possible solutions:
Create a copy of the font, set its lineHeight to the value I need, and create a separate LabelStyle with that font; or
Write a custom Label for myself which implements setLineHeight.
The first idea seems wasteful, the second is likely a bit complicated, so I'm hoping there's an easier way of achieving a temporary lineHeight in Labels.
Nathan Sweet, one of LibGDX's core developers has kindly suggested a solution, which is working perfectly:
Override Label#layout, set line height, call super.layout, set line height back. You need to use layout and not draw because layout computes and caches the glyph positions, draw just draws them.
You can change the LabelStyle of a single Label by doing something like this:
//skin is the skin that you use
Label myLabel = new Label(text, new LabelStyle(skin.get(LabelStyle.class)));
And then you can modify the style without affecting all the labels.

Background-image opacity and :hover

Is it possible to only trigger a div's mouseover when the cursor is over an opaque part of the div's background image? Perhaps via Javascript?
All I can find with Google are old IE PNG fixes.
This looks like a similar question to this one: Hit detection on non-transparent pixel
I suppose this could also be done for background image by getting the attribute with jQuery:
$('#myDiv').css('background-image');
I haven't personally done this, but it seems like a viable solution. This will only work for modern browsers, but you should be able to make it back-compatible with excanvas.
It is possible, just not very easily. You'll have to use a lot of Javascript.
You'd want to attach to your <div>'s onmousemove event, which returns the X,Y coordinates of the cursor. Your event handler function would then test to see if the cursor is in the correct place in order to trigger an alternative onmouseover event.
Implementing the "is the cursor over an opaque pixel or not?" test can be done two ways: the first is to create a simple mathematical expression (say if the opaque parts of the image make neat rectangles, circles or polygons). The more difficult (and less browser-supported) way is to load the background image into a Canvas object and then get the current pixel value's opacity figure and take it from there, like so:
var pixel = canvas.getImageData(x, y, 1, 1).data;
var alpha = pixel[3]; // assuming RGBA
if( alpha > threshold ) onMouseOver(); // raise the event
Another alternative is to create an entirely transparent div (or some other element) positioned and sized so that it only covers the opaque part of the div below, then just test the mouseover of that element's box.
It's a bit of tweaking but why don't you add a class to your opaque div, and use JavaScript to check for it?
In jQuery:
$('div').mouseover(function(){
if ($(this).is('.opaque')) {
//Some actions
}
});

Strange difference between HTML and SVG span rendering in Safari

This question is a little specific and I am hoping someone here can shed some light on a potential solution for me.
All of the following points are important:
I am writing some HTML pages that are going to be read on a third party hand-held device.
In order to fit the requirements of this device each word must be in a separate span, this is for an upcoming feature of the device that I am not allowed to go into, but it has to be formatted like this.
This HTML is being converted from SVG, the SVG is created from Adobe Illustrator documents.
The only place I have any control of the creation of the HTML is in the conversion from SVG to HTML.
My problem is this, in SVG text is broken down into "text" nodes and tspan nodes. Look at this simple SVG, note how I am changing the Y coord on the first tspan.
<text><tspan y="50">Hello</tspan><tspan> World</tspan></text>
When this renders in a webkit based browser, like safari, the sentence "Hello World" is displayed with the word "World" right next to the word "Hello".
In my converted HTML example:
<div><span style="position:absolute;top:50px;">Hello</span><span> World</span></div>
"Hello" is displayed with a y offset of 50, however "World" is displayed in the top left corner origin of the page.
This is frustrating as I do not have the coords of where the "World" span should be placed in the SVG (as Illustrator does not need this coord to render it correctly). Also, there may be one or more tspans in the SVG with altered positions which will prevent me from applying the style to the div.
In short, does anyone know if there is an attribute I can set to place the second span directly after the first?
Thanks
You could style the div instead of the span
<div style="position:absolute;top=50px;"><span>Hello</span><span> World</span></div>
That would keep text-chunks together and positioned relative to each other, but you could still have a span for every single word
Have figured this out after trying a bunch of different things.
It is actually very straightforward, however I didn't realise spans could be nested so I am going to let myself off.
<div><span style="position:absolute;top:50px;"><span>Hello</span><span> World</span></span></div>
The trick is to wrap all the words that need to be grouped together in a span. Hopefully this helps anyone who is stuck on a similar issue.

TextField autoSize+italics cuts of last character

In actionscript 3, my TextField has :
CSS styling
embedded fonts
textAlign : CENTER
autoSize : CENTER
... when italics are used the very right character gets slightly cut off (specially caps).
It basically seems that it fails detecting the right size.
I've had this problem before but just wondered is there a nice workaround (instead of checking textWidth or offsetting text etc.)?
Initialize your textField as you always do, using multiline, autosize, htmlText...
Then do this little trick :
// saving wanted width and height plus 1px to get some space for last char
var savedWidth = myTextField.width + 1;
var savedHeight = myTextField.height + 1;
// removing autoSize, wich is the origin of the problem i think
myTextField.autoSize = "none";
// now manually autoSizing the textField with saved values
myTextField.width = savedWidth;
myTextField.height = savedHeight;
Not that it is much comfort to you, but Flash sometimes has trouble with this seemingly simple task. CSS styling of html TextField was a nice addition but it has caused headaches for text-rendering. In fact I very rarely use CSS for styling text for that reason. I can only imagine that combining bold, italic and normal type faces within the HTML causes Flash to get some of the width calculations wrong which causes autoSize to set the mask a tiny bit short. I hope very much that the new text rendering engine in Flash Player 10 will finally fix these issues (it certainly looks better in theory).
So my solution is never to use HTML with the exception being when I require <a> links in my text ... and there are even some tricky text shifting issues there. In those cases I avoid mixing different font weights and font styles within the same text field. All other cases I use TextFormat directly on TextField.
I suppose if you can't get out of your current architecture (for some reason) you could try adding to the end of your html encoded strings. Or you could manually set the width of the field and not rely on autoSize (as you have mentioned). But if you keep on the CSS/HTML route you may find another new and painful limitation just when you don't want it.
I've had issues with TextField masks behaving differently in the Flash preview, and in the actual browser plugin. Usually, and this is strange to me, it would appear more correctly in the browser. Have you tried running the swf in a browser to see if the problem is actually an annoyance rather than a permanent problem?
I had said this:
My in-ideal approach to solving this is to attach a change event to the TextField which always adds a space after the last character of the field. And then to remember to trim this space off when using the value.
But that didn't take into account that this probably doesn't have a change event and that it's an HTML rendered text field. To add a trailing space in the HTML text field throw in an again, that's not really fixing the problem.

flex textflow dyniamic height

In my flex application I have scenerio like this:
parent to child
Vbox->Canvas->Sprite->Textflow
In this scenerio now I need to have dynamic height of the textflow & its parents. Here the root parent is the itemrenderer of the datagrid I have.
I need the heights of rows to be adjust according the content in it.
Right now I am importing the xml to textflow, then getting the number of lines, text height. Then removing the textflow & adding it again with the measured height according to the number of lines & text height.
How can I achieve it without removing & adding it again, coz it is taking much time in updating?
Thanks in advance.
Right might be a little late to answer this but someone else may benefit.
On the canvas or display object housing the TextFlow and sprite add a creationComplete functon.
I don't know if this step is necessary, but it works for me. Add a label with the text thats going to go into TextFlow (with the same font and fontSize), add a creation complete listener to that as well.
Get the height and width from the newly created label e.target.width e.target.height (in the function listening to the creation of label). Set the displayObjects (in the above case Canvas) height and width to these values, then proceed to add the sprite and textflow.
Note: this was a lazy way for me, label uses measureText which would be a more efficent way of doing this.