In the Haskell Gloss library, one draws text with the Text constructor of the Picture type. But how, then does one find the width (and height) of such a picture?
Here's how text is rendered in Gloss:
Text str
-> do
GL.blend $= GL.Disabled
GL.preservingMatrix $ GLUT.renderString GLUT.Roman str
GL.blend $= GL.Enabled
The important point here is that it calls renderString. Looking at the documentation for renderString, we immediately see two other useful functions: stringWidth and fontHeight. As such, you can get your width and height like this:
import Graphics.UI.GLUT.Fonts
do
width <- stringWidth Roman str
height <- fontHeight Roman
Related
I would like to create a text box that I can set to have a particular width and height. However, the text box that I create appears to not have a width and height in the first place. E.g. the following code:
main = do
putStrLn $ show $ width $ myText
putStrLn $ show $ height $ myText
mainWith myText
myText :: Diagram B
myText = text "here" # lw 1 # fontSizeL 0.2 # fc grey # scaleX 1
results in a blank diagram (with no text), and prints "0.0" as the width and height of the text box:
ghc --make Main.hs && ./Main -o circle.svg -w 400
[1 of 1] Compiling Main ( Main.hs, Main.o )
Linking Main ...
0.0
0.0
In order to get the text to appear it seem that I need to place it on top of something else. E.g. the following code:
main = do
putStrLn $ show $ width $ myDiagram
putStrLn $ show $ height $ myDiagram
mainWith myDiagram
myDiagram :: Diagram B
myDiagram = myText <> myBackground
myText :: Diagram B
myText = text "here" # lw 1 # fontSizeL 0.2 # fc grey # scaleX 1
myBackground :: Diagram B
myBackground = rect 1 1 # fc black
produces the grey text within a black background as expected.
Why does the text box not have a size?
How can I set the length and width of a text box to a certain value?
Why does the text box not have a size?
Because text handling is not only highly dependent on the backend used to render the diagrams (cf. the User's Guide) but also potentially dependent on how fonts are configured in the system used to run the program.
How can I set the length and width of a text box to a certain value?
Use text handling functions provided by your chosen backend, if they exist. For instance, diagrams-cairo provides functions that use Pango to render text on its own, though with the significant annoyance of them being IO functions, as they need to query font information from the system.
Use SVGFonts to stroke the text independently of the backend. There are a few inconveniences with this approach as well (limited choice of fonts unless you follow the instructions in the documentation to convert your chosen font to the SVGFonts format yourself; fonts with large sets of characters might lead to a small but noticeable delay when they are first used by your program, as they have to go through an initial processing), but at least you don't have to bother with IO or backend-specific quirks.
This relates to the "gm" extension for node, http://aheckmann.github.io/gm/docs.html
I need to add some text centered around a bounding box (horizontally is enough). The function drawText() requires x,y coordinates, but there is no way to draw centered text.
I would otherwise need a function which can return the width of a text string in the font/size given, so I can calculate my starting x position in javascript, before calling drawText().
You can use the region and gravity functions this way:
gm(filePath)
.region(WIDTH, HEIGHT, X, Y)
.gravity('Center')
.fill(color)
.fontSize(textFontSize)
.font(font)
.drawText(0, 0, 'This text will be centered inside the region')
I'd like to build a function that takes a given Unicode character and a given TrueType font and rasterises the corresponding glyph into a two-dimensional 1-bit-per-pixel bitmap.
Something similar to this:
rasterize :: Font -> Char -> Size -> Bitmap
rasterize font char size = ...
Requirements
The rasterize function should:
produce a bitmap of maximal width w and height h, such that w <= size and h <= size
rasterize the glyph so that it completely fills the bitmap, leaving no padding.
The Bitmap type should support the following operations (or similar):
width :: Bitmap -> Int
height :: Bitmap -> Int
bit :: Bitmap -> (Int, Int) -> Bool
where bit b (x, y) should evaluate to True if (and only if) the bit within Bitmap b at index position (x, y) is set.
Question
Are there any Haskell libraries that can already do this, or something similar?
Example
Evaluating the expression rasterize fontUtopiaStandard 'o' 64 would result in a Bitmap b that if rendered would look similar to the following image (viewed at 800% scale, with grid), where (width b, height b) = (60, 64):
Notes
I've already tried using the stb-truetype package, but any attempts to get at the pixel data seem to cause segmentation faults, even when compiling with version of GHC (6.12) similar to the version on which the package was tested. (I can provide more details of the segfaulting code if anyone's interested.)
I'm aware of the existence of libraries that render TrueType fonts within an OpenGL context, but I can't see how to get access to the pixel data.
I'm using cairo (specifically, the haskell bindings for it) to render a game world every tick. As it is now, I'm generating my entities by creating rotating and translating,creating a path, and filling it. I'm looking for a much more efficient way to handle doing this. What I'd ideally like to do would be to create some sort of sprite and just copy it onto the surface at the correct coordinates.
How would I go about doing this? Or, if I'm thinking of this the wrong way, how should I do it otherwise? I don't really have experience with game making or cairo and I'm just doing this for fun. Any advice is appreciated.
The clock demo includes a complete example of how to cache a cairo render. See especially the redrawStaticLayers action:
let redrawStaticLayers = do
(width, height) <- widgetGetSize window
drawWin <- widgetGetDrawWindow window
background <- createImageSurface FormatARGB32 width height
foreground <- createImageSurface FormatARGB32 width height
let clear = do
save
setOperator OperatorClear
paint
restore
renderWith background $ do
clear
drawClockBackground True width height
renderWith foreground $ do
clear
drawClockForeground True width height
writeIORef backgroundRef (Just background)
writeIORef foregroundRef (Just foreground)
please , see following image, here you can see blue rectangle is custom shape bounds and custom shape is shoe , i want to find area of a portion written in image and i want that area in form of rectangle
do is there any path iterator concept ?
Note
custom shape i derived from image of the same size.
I would do it like this:
1.create table for all bounding box-rect perimeter lines
each value in it will represent the empty space length form border line to shape
something like this:
the values are found by simple image scanning until first non space color found
2.now bruteforce find the biggest rectangle area
x,y = top left corner
for xs = 1 to bounding box width
now scan the max valid height of rectangle from x to x + xs (x grows to the right)
// it should be the min y0[x..x+xs]
remember the biggest valid area/size combination
do this for all 4 combinations (star from the other corners)
I now Brute-force is slow but
you can divide perimeter lines not by pixels but with some step instead
also I am sure this can be optimized somehow
for example by derivation of perimeter find the extremes and check from them backwards
when the size will start shrinking then stop ...
of course take in mind that on complicated shapes this optimization will not work ...