Since FMX doesn't have an equivalent of TRichEdit, how can I output a differently colored text? I'm writing a console (as in a Quake-style console, to clarify) output visual control for my application, and I don't see any way to solve it, except to draw the text myself, complicated by many factors (like scrolling).
Now after thinking about it, since TTextLayout doesn't work as intended, I think that it can be done by creating an array of colored as needed TLabels in a TFlowLayout, but there are some things to consider: performance and memory usage, copy-pasting and word wrap. When I add a string to log, split it into strings so each string is of one color and for each string create a TLabel with text and color set accordingly.
Related
I'm rendering text with SkiaSharp for various platforms. I have problem with arabic script. I've created simple shaping routine and I have nicely connected glyphs. But diacritics is off completely.
Is there an easy way how to render/position diacritics? Like another table, which tells that after this char, put this glyph which represent diacritics in middle position, or something like that.
I'have tried HarfBuzzSharp, it's working ok, except Android (where it is returning zeros to all glyph positions).
I am trying to draw an NSAttributedString (actually, a constructed NSMutableAttributedString) where the "original" text has been struck and replacement text inserted above it (I'm trying to replicate the look/feel of an Ancient Greek manuscript).
My technique is a combination of NSBaselineOffsetAttributeName with NSKernAttributeName, but it appears that using a negative value for NSKernAttributeName "wipes away" the strikethrough of the text, even if the characters don't overlap.
If I put an extra space after the "A" character (in the original text), the "A" gets the strikethrough, but the "EI" is also offset to the right. So, it appears that the offset/kerning of the "EI" text affects how much of the strikethrough actually occurs.
Here's what I'd like to reproduce (I don't care about the angle; it's not about a picture-perfect reproduction; just the gist):
Here's what is currently happening:
This is when I add an extra space after the strikethrough:
So, the only other thing I can think of would be to render a separate NSAttributedString in the correct place, separate from the current one, but I have no idea how to calculate the location of a specific character in an NSAttributedString when it's drawn. I'm drawing to a PDF, not to any on-screen control like a UILabel. Alternatively, I could draw the "strikethrough" myself as a line, but that seems to still require knowing the coordinates for the text in question, which is calculated on-the-fly, and I hope to use this method to reproduce a large sample of ancient texts, which means doing it by hand just isn't a good answer here.
Anything I'm missing, or any out-of-the-box ideas to try?
I have a master image which I edit in gimp to get the look and feel wanted. I then want to use a python script to produce a bunch of new images with the text (on several different layers) changed. I would like to leave the font, size, italicized or not, etc. alone.
I've successfully changed the text in my batch script with this function:
pdb.gimp_text_layer_set_text(layer, text)
The problem is this also overwrites the font and other text parameters that I had picked out in the master file. Is there a way to change just the text and leave the font alone?
Alternately, a more clunky way would be to try and save everything important about the font before the change and try to reapply it. This is what I've tried:
# Find the text layer
text1_layer = filter(lambda x: x.name == 'text1', im.layers)[0]
# Save the font
font = pdb.gimp_text_layer_get_font(text1_layer)
font_size, font_unit = pdb.gimp_text_layer_get_font_size(text1_layer)
# Set the text
pdb.gimp_text_layer_set_text(text1_layer, tex1_text)
# Restore the font
pdb.gimp_text_layer_set_font(text1_layer, font)
pdb.gimp_text_layer_set_font_size(text1_layer, font_size, font_unit)
Unfortunately, that doesn't seem to work consistently. It looks like the get_font and get_font_size commands retrieve the right font for one of the layers, but not for the others. It doesn't seem to preserve italics etc., and I wouldn't expect it to preserve whether or not text is underlined.
A third option would be to hard code in the font. I would need to go through all the text fields, figure out what the font parameters are and hard code them in for each one. Then, if I redesign the master file (which I will do a lot), I have to repeat the process. This shouldn't be necessary.
I've done a bit more research and found a solution that works for me in gimp, however, it sounds like you should probably be using something other than gimp, such as imagemagick, if you're doing much text editing from a script.
The solution is, when you change text in the gimp editor you need to change the font in the tool dialog box, so it's set as a property of the layer, instead of just selecting the text and changing the font in the floating font box that shows up - that changes the font of the text you selected, but leaves the base font of the text layer unchanged.
In turns out that gimp text functionality is pretty poor, and there are lots of complaints surrounding issues like this online. There is some hope for the future. Apparently gimp supports a markup language for text. You can get the markup for your text this way:
pdb.gimp_text_layer_get_markup(layer)
Unfortunately, there is no set_markup function - even though it's been commented on and requested for 3-5 years now, so don't hold your breath. If such a function existed, then the get_markup and set_markup functions would give a script complete control over text. It doesn't exist, however, so if you want to change pieces of text (eg. to add italics to a word), you have to create separate layers. If all your text is to be formatted the same, you can edit it via script or editor, and as long as you set it in the text layer properties (done via the tool box in the editor, and the only way you can change font in a script), then the set_text function in a script will maintain font, etc.
https://bugzilla.gnome.org/show_bug.cgi?id=724101
http://gimpchat.com/viewtopic.php?f=9&t=10101&p=132782&hilit=change+text+markup#p132782
Not really a satisfactory answer, but too big to post as a comment.
Yes, the text layer API wasn't updated to follow the new capabilities. Actually all the info is in a gimp-text-layer "parasite":
parasites=layer.parasite_list()
if parasites and 'gimp-text-layer' in parasites:
data=layer.parasite_find('gimp-text-layer').data
pdb.gimp_message('Text layer "%s": %s' % (layer.name,data))
This parasite doesn't seem to exist until the image has been saved at least once.
However, even though you can replace the parasite data, it doesn't change the text layer, and to make it worse, it seems that Gimp detects the change, assumes that the layer text data is corrupt, and makes the layer a plain bitmap when saving the image.
Now, poring over the source code, there are mentions of a GDynText plugin that you can find on SourceForge and that advertizes itself as:
GIMP Dynamic Text is a GIMP plug-in that works like the text tool but allows you writing multi-line text and made you able of modifying it later as you want (text/font/font size/color/...).
So you could be lucky, or not...
How can I fully justify a block of text (like MS Word does, not only on the right and not only on the left but on both sides)?
I want to justify some texts (mainly arabic text) adjusted to certain screen size (some handheld device screen actually, and its text viewer doesn't have this function) and save this text as justified. So I can reload and reuse it again elsewhere.
(The problem with MS word is, that if you copy the justified text from MS Word and paste it to another editor it'll copy it un-justified).
Update : for now I'm thinking of doing it like this:
get-a-word
get-word-width
add-word-to-total-Word and add-Word-width-to-total-word-width
check if total-Word-width = myscreen-width then continue
else if total-Word-width is between myscree-wdith and (myscreen-width -3) then
add-spaces-To-total-word until it = myscreen-width
This is what I'm thinking now, but I put this question up and hope to see if there is a better solution, or somebody else already implemented it.
PS: I hope I have made my question clear and I'm sorry for bad expression if there is.
edit1 : changed the title to make it more clear.
If you want to justify plain text, you can only add extra spaces to the lines to get them align on the left and right. Unfortunately the character widths differ in fonts; so doing it this way will only work for a certain font, unless you limit yourself to monospaced fonts where all characters have the same size.
If you want a result like in Word, adding spaces won't cut it. Word will not add spaces, but stretch and shrink the existing spaces. This information is lost when you copy and paste it into another app.
Either way, justifying is an optimization problem. If you are interested in a good solution and its implementation: have a look a TeX. For an implementation that works on plain text with monospaced fonts have a look at par
There are some API calls that may help:
ExtTextOut and GetCharacterPlacement
Look at the GCP_JUSTIFY flag for GetCharacterPlacement
ExtTextOut is used by Canvas.TextRect
The problem you are going to face is always going to be differences in the rendering of the font. Word handles full justification by adjusting kerning as well as adjusting the number of pixels between words by a few (either way). The end result is lined up both margins. This pixel adjustment is done BOTH ways, and as evenly as possible.
To properly handle this in your portable device you will have to also perform the same algorithm for the display of the text there.
If this is not possible, then the ONLY way you can even get somewhat close would be to add whitespace between words.
As has been pointed out in other answers Word does full justification by stretching the existing spaces often by very small amounts. This is only possible if you have full control over how your text is drawn on the screen (which word - or any other windows program has).
You only real option in this regard would be to implement your own text viewer on the platform you are targeting. Eg you would need to draw the text on the screen yourself (any platform that allows games should allow you to draw on the screen). However this seems like an awful lot of trouble to get justified text.
Sorry couldn't be of more help.
I saw this picture and now wondering if/how you can do this in Delphi. The highlighted/selected text shows two forms of formatting, i.e. highlight color and hash lines.
http://img9.imageshack.us/img9/4121/easilyselecttextofonela.jpg
I've done something very similar recently in a bible application, also done in Delphi.
The user can select a single verse and single words of the selected verses. (But this feature is not released yet, so don't bother looking for it)
I used the web browser control from Microsoft and added my own kind of selection handling.
I've done the formatting by enclosing the relevant parts with span elements and changing their CSS style. When the selection gets removed, I also remove the enclosing elements.
The hard part was backing the "visual" selections with a selection data structure and handling all the selection events (clicking, shift-clicking, shift-ctrl-clicking, ...)
Embedding IE seems to be an easier way to do this as DR says, but you can also do this manually by drawing it all on a canvas, an easy way would be to create two bitmaps (one without a selection and another selected (could be as complicated as you like - dashed, colored, ... )), and you need to know the positions/rects of all your characters which would be somewhat difficult for long texts.
You basically show the unselected bitmap, and overlap the selected parts by portions of the second image.
You would also need to handle the selection manually by OnMouseDown, OnMouseMove, OnMouseUp...