I am trying to make text appear on a FXCanvas. when I use this code:
def score_box(event)
FXDCWindow.new(#canvas) do |dc|
dc.drawText(640, 450, #score)
end
end
but it gives me an error saying I need to select a font, how do I do this? or could you provide anyway to make text on a canvas? Thanks
-bipolarpants
You need to select an FXFont object into the device context (dc), e.g.
FXDCWindow.new(#canvas) do |dc|
font = FXFont.new(...)
font.create
dc.font = font
dc.drawText(640, 450, #score)
end
Related
I'm trying to output text to the main window with unicode character like that
def initialize
super 800, 800
self.caption = 'Chess'
#font = Gosu::Font.new(self, Gosu.default_font_name, 100)
end
def draw
text = "Chess \u2658".encode('utf-8')
#font.draw(text, 100, 100, 10, 1, 1, Gosu::Color::BLACK)
end
but the window displays only the 'Сhess' string without unicode symbol '♘' as supposed.
What I have tried so far:
to change font name itself, 'Gosu.default_font_name' to 'Serif', 'Arial', 'Hack' - same result only 'Chess' string changes font but not displaying glyph
use symbol '♘' instead of unicode code
use .draw_markup, .draw_text, Gosu::Image.from_text.
use different unicode code, for example with cyrillic letter '\u0416' it worked as supposed.
use different encoding arguments.
use different colors.
I looked for similar problems on the Gosu forum, but I could not find anything.
You need to use a font that includes those Unicode characters or Gosu's internal font rendering code will return a 0 width image for drawing that character.
A font like: https://fontlibrary.org/en/font/chess
require "gosu"
class Window < Gosu::Window
def initialize(*args)
super
#font = Gosu::Font.new(28, name: "Chess.odf")
end
def draw
#font.draw_text("♘\u2658", 10, 10, 10)
end
end
Window.new(100, 100, false).show
Our users are giving us Emoji and a lot of other weird characters and the built-in Helvetica can't handle it. Neither can Google's Noto fonts by themselves - I need to figure out how to declare the Noto Font Family in HexaPDF and I can't figure out how to do that with the given documentation. OpenSans was an improvement, but I still want more glyph coverage than that.
Update:
I used this method to set the font:
def self.pdf_summary_font
##pdf_summary_font ||= File.open(Rails.root.join('public',
'OpenSansEmoji.ttf'), 'r')
end
canvas = page.canvas(type: :overlay)
canvas.font(self.class.pdf_summary_font, size: 10)
However, no Noto font ever worked with this - I would get errors like "Missing glyph - 'A'"
The best I could do was to use OpenSansEmoji, and replace missing glyphs with the following block:
begin
style = HexaPDF::Layout::Style.new(font: canvas.font, fill_color: color, stroke_color: color, align: :left, valign: :center)
fragment = HexaPDF::Layout::TextFragment.create(str, style)
layouter = HexaPDF::Layout::TextLayouter.new(style)
layouter.fit([fragment], w, h).draw(canvas, x1, y2)
rescue HexaPDF::Error => e
if e.message.include?('Glyph for')
glyph = e.message.match(/\{(.*?)\}/).captures.first
str = str.grapheme_clusters.map do |char|
if char.dump.include?(glyph)
"\u{FFFD}"
else
char
end
end.join
retry
end
Have a look at https://hexapdf.gettalong.org/documentation/reference/api/HexaPDF/index.html and the configuration option "font_map". This allows you to declare any TrueType file and use it.
You could also use the path to the font file directly with the Canvas#font method.
If you need to cover a wide array of characters you need to use a single font that covers all of them, one of the fonts included in this ZIP file should probably work (Google says 582 languages, 237 regions included).
I have a text object in ruby 2D showing score. How do I update the text?
I have this so far
update do
text = Text.new("Score: #{#score}")
end
Instead of replacing it, it is creating a new text object on top of it. How could you replace it instead of adding it on?
Based on docs it seems like you need to instantiate the Text object outside of the update loop. This will draw it to the screen "forever" until you call the remove method.
In your current code you are just instantiating a new object every time, and Ruby 2D is secretly keeping it around even though you don't have it assigned to a variable.
Unlike some other 2D libraries like Gosu, Ruby 2D does not stop drawing something until you explicitly tell it to.
Try
#text = Text.new("Score: #{#score}")
update do
...
#text.remove # At a time you want to stop displaying that text.
...
end
Adding and removing objects in Ruby 2D
here a simple example how to use the Text class in ruby2d
require 'ruby2d'
sector = 3
txt = Text.new(
sector.to_s,
x: 10, y: 10,
size: 20,
color: 'white',
z: 10
)
on :key_down do |event|
case event.key
when 'a'
sector += 1
txt.text = sector.to_s
when 's'
sector -= 1
txt.text = sector.to_s
end
end
show
I'm trying to build a PDF from user-generated content and I have a chunk of information that should be grouped together. I know of the group method to make sure text all gets rendered together, but this doesn't seem to work with a mix of text and images. Is there something that can do this with Prawn, or do I need to try to calculate cursor position and manually linebreak?
Edit: For illustration of what I'm looking to do:
pdf = PDF::Document.new
20.times do
pdf.group do
pdf.text "Something"
pdf.image "path/to/image.jpg"
pdf.text Time.now.to_s
end
end
And I would expect to not ever have "Something" on one page and the image on the next, but that is what I see. Is there some way I can achieve what I want?
Okay, I've figured it out. Prawn does not seem to take the image height into account when grouping, but you can hack your way around it:
pdf.group do
pdf.text "Best regards, (...)"
pdf.image "#{Rails.root}/vendor/signature.jpg", {
:height => 30,
:at => [0, pdf.y.to_i - #bottom_margin]
}
pdf.move_down(35)
pdf.text " "
end
The trick is to use absolute positioning for the image, and move the text cursor down manually.
Shoes is very handy GUI tool. I would like to do a search form so that a user is helped to navigate through larger texts for editing. For this I need to move the cursor within an editbox element.
Here you'll see my question in code:
Shoes.app do
stack do
p=para "After pressing 'search' a question will arise"
box=edit_box
box.text="One\nof\nthe\nmost\nstriking\ndifferences\nbetween\na\ncat\nand\na\nlie\nis\nthat\na\ncat\nhas\nonly\nnine lives."
flow :margin_top=>0.1 do
search=edit_line
button("search") do
pos=box.text.index search.text
y = box.text[0..pos].split.size-1 if pos
if not y.nil?
#For example if you searched "only" then
#cursor should jump/scroll to line 17.
#
#Anything there for cursor positioning,
#like: box.cursor=[0,y]
#
p.text="How can I move editbox's cursor in line #{y+1}?"
else
alert "'#{search.text}' not found"
end
end
end
end
end
Is there is any way to change cursor's position of an editbox? If not, do you know an alternative way of implementation?
Unfortunately, Shoes doesn't seem to provide any way to do that. These are the only methods defined on EditBox (it inherits from Native, which has several methods, but again, none to reposition the cursor).
rb_define_method(cEditBox, "text", CASTHOOK(shoes_edit_box_get_text), 0);
rb_define_method(cEditBox, "text=", CASTHOOK(shoes_edit_box_set_text), 1);
rb_define_method(cEditBox, "draw", CASTHOOK(shoes_edit_box_draw), 2);
rb_define_method(cEditBox, "change", CASTHOOK(shoes_control_change), -1);
http://github.com/why/shoes/blob/cea39a8bf9a5b7057b1824a9fab868d1f8609d69/shoes/ruby.c