How to vertically align picture in line using python-docx - python-docx

I am adding a picture (some latex converted into a PNG using matplotlib) to my text using the following code:
par = doc.add_paragraph()
par.add_run().text = 'foo bar baz'
par.add_run().add_picture('pic.png')
par.add_run().text = 'blah blah blah'
This works OK, except that the picture pic.png is not vertically aligned in the rest of the text in the document:
I can get the alignment manually in MS Word by adding a character style with the advanced vertical alignment property set to "lowered by 10pt":
The problem is that I have no idea how to do this programatically using python-docx. Conceptually the steps would be to compute the size of the image, create a character style that was lowered by half that size minus half the size of the font and apply the style to the run containing the picture. How do you create a raised or lowered font style in python-docx?
For reference, here is pic.png:

Your image has a fairly large (transparent) border around it. I added a single pixel border inside its extents here to make it visible:
I expect Word is aligning the bottom of the image with the baseline (as expected). One approach would be to see if there was a way you could specify zero bottom border.
You could also try subscript on that image run. I'm not sure what it would do but it's worth a try. So something like this:
run = par.add_run()
run.add_picture('x.png')
run.font.subscript = True
If you find the run that you manually set to "lowered by 10pt", you can view the XML for it like this (aircode):
run = vertically_adjusted_run() # however you get ahold of it
print(run._element.xml)
I expect you'll see something like this:
<w:r>
<w:rPr>
<w:position w:val="20"/>
...
... where the w:position element sets the adjustment from the baseline. The value is specified in half-points.
Anyway, neither this adjustment nor even that low-level element are supported by python-docx yet, so you'd need to get in there with lxml calls to do the needful if you wanted it badly enough.

Related

Setting QTextDocument painter's rectangle (where to paint)

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.

Reduce area of svg text

I am currently creating a word cloud using an in house developed library, it uses the svg element text to display the words, the problem I have encounter is that the area of some words sometimes overlaps other words as you can see if you inspect test1 in this jsfiddle, this becomes a problem if the words must be clickable.
I want to know if it is possible to reduce the area of the text to the minimum, just wrapping the word, a small padding is accepted.
I have already tried the solution posted in this answer but it didn't work.
I would prefer a css solution if it exists rather than messing with svg but if there is no other option that will do.
Edit: Ok, enough reputation to post images. What I currently have:
What I would like to have:
There are two problems; I currently have only a solution to one. Your text example is misleading. Try Text1g instead to see the descent (i.e. the amount of space below the baseline which the g needs). If you do this, then you'll see that the texts really overlap - you just don't notice because your test text doesn't contain a good set of test characters.
Apart from that, I see that the element is 67px high while the font-size is only 60px. I don't see where the additional 7 pixels are coming from. It's not padding and not margin :-/
Why do you need to know the minimum bounding box?
If it is because you are linking with the element, or applying click events to the words, then you should investigate the pointer-events attribute.
You possibly want something like:
<text ... pointer-events="fill">ejecutar</text>
You will only get events when the pointer is over the fill of the words. This might be a bit fiddly for clicking though because the holes in words will not be clickable.
You could ease that by putting an invisible <rect> of an appropriate size in front of the word with pointer-events="fill". The "fill" value will attract events for where the fill would be even if it is invisible. However that requires you know the bbox of the word, which we already established you don't have (?).
You could give the words an invisible fat stroke and use pointer-events="all". The invisible stroke will make the clickable area (invisbly) fatter and hence the inter-word holes smaller.

display text as square symbols instead of letters

Is there a simple css way to display text with every letter replaced with a filled square?
My idea was to find a font-family that has squares for all letters, but I didn't find anything like that existing. Google is no friend as it gives hits of posted issues with boxes that appear when fonts fail in some way.
Letters should be displayed as squares, not replaced with squares. Also, I need to be able to control the square fill color with the usual html/css.
I'm fine to use font-face, but am trying to avoid the learning curve for creating my own font.
Update: here is an example:
div.innerHTML = "some arbitrary text".
Should be displayed like this:
"■■■■ ■■■■■■■■■ ■■■■".
#NoobEditor is right although. Many online font editors available (e.g.: http://fontark.net/farkwp/ ), you can create such font family in few minutes and can embed with your app.
Get a square font, define it in your we page style, asign it to an object, a div must work, put your text there. Voila.

Spacing width between lines

I've got a textbox which has text that is coming from a stored procedure. I'm trying to increase the line spacing between text so that the text doesn't seem so "squished together".
i.e.
ABC
DEF
I want slightly more spacing between ABC and DEF. Using the newline operation isn't feasible, because the spacing will be too large.
I've tried using the line spacing property option but that hasn't made a difference.
Edit: DEF should be directly under ABC in the example.
What you want is unfortunately not possible in SSRS. From the relevant documentation, here's the limited list of what you can do with CSS in reports:
text-align, text-indent
font-family
font-size [...] Supported units are: in, cm, mm, pt, pc. [...]
color
padding, padding-bottom, padding-top, padding-right, padding-left
font-weight
Your question speaks of "line spacing" (i.e. line-height?), but your examples seem to be about word-spacing. Unfortunately, neither's available in SSRS.
For word-spacing I can only think of hacks and workarounds, most of which aren't pretty:
Use SQL or expressions to double spaces, e.g. Replace(Fields!Xyz.Value, " ", " ")
Choose a different font that allows for more space between words.
Beyond that workarounds get even less pretty.
For word-spacing I can't really think of any workarounds, except for the one you used (linebreaks) or using a different font.
Bottom line is probably that you can't really do anything about his, AFAIK.
I was able to control this by double spacing my text and then changing the font size of the second line break
For example:
text <--CRLF, 8pt
<-- CRLF, 4pt
text
It's not very scalable, but it does the job.
Try adding padding in the textbox and changing the vertical alignment. It will increase the space between the cells. Worked for me.
I know this is an old topic, but you can do that by changing SpaceAfter and SpaceBefore properties.
Try this:
TextBox Properties -> Font -> Line Spacing -> Custom
UPDATE:
This is Microsoft bug..
The line spacing depends on font size... option below doesn't work..
Yes you can make a line any height you want. When you select the line on the far left side of the row drag your mouse to increase the row height. Set the vertical alignment in the text box to Top. This will stop the data from moving to the center of the box or you can use padding options for the bottom.
There isn't a way to natively do this, but a very customisable way is to simply add lines in between your lines manually and change the font-size so that the line size decreases respectively. A bit time-consuming but better than nothing.
I finally found that if I add blank expressions within my text I can trick SSRS to double space.
right click-> Create Placeholder
Do this mid sentence on the second or subsequent line
Set the Value in Placeholder Properties to ="" (*an empty string*)
you will have text in your SSRS document that looks like this:
I want to <Expr>double space.
Now highlight the <Expr> and set the text size to double the font you're using
And the report will render with the effect of double spacing.

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.