Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Autoscale doesn't handle vertical text overflow #305

Open
andymeneely opened this issue Apr 23, 2020 · 3 comments · May be fixed by #386
Open

Autoscale doesn't handle vertical text overflow #305

andymeneely opened this issue Apr 23, 2020 · 3 comments · May be fixed by #386
Labels

Comments

@andymeneely
Copy link
Owner

Quote from @nickolasreynolds regarding our autoscaling text feature.

...the native one ignores vertical overflow, which can result in cutting off the bottom of long strings or strings with carriage returns. Also, I needed to autoscale some lines with wordwrap disabled (like the name, type, and copyright), which I couldn't get the native scaler to do. Here's some code showing what I came up with, and also showing the sort of relative / percentage-based positioning system I implemented. (Also please feel free to use any of my code or ideas now and in the future, under whatever license Squib is published, if you think they are useful. I'm simply showing you the "copyright" section of the layout I'm making because it's clean, and I'm not doing anything too complicated or fancy there, but it still has all the functionality I wanted to show you.)

##-COPYRIGHT----------------------##

copy_font  = PLAIN_FONT	
copy_size  = 5	
copy_color	= '#BBBBBB'
box_list << copy_box = Box.new(
	card_box.xc,                  # x: Horizontal center of card_box
	text_box.y2(-1.5),            # y: Bottom edge of text_box, minus 1.5% of its height
	text_box.w(95),               # w: 95% of text_box width
	card_box.y2 - text_box.y2,    # h: Bottom edge of card_box minus bottom edge of text_box
	'cywh'                        # Mode: Above givens are x-center, y1, w, h
)

box_list << copy_shadow_box = Box.new(
	copy_box.x1 + copy_box.h(4),  # x: Left edge of copy_box, plus 4% of its height
	copy_box.y1 + copy_box.h(6),  # y: Top edge of copy_box, plus 6% of its height 
	#  ↑ 
	#  └ ( copy_box.y1(6) would also work to specify this y1, but for readability 
	#    ( I wanted to highlight how *both* x1 and y1 were being augmented by the 
	#    ( height of copy_box. 
	copy_box.w,                   # w: copy_box width
	copy_box.h,                   # h: copy_box height
	'xywh'                        # Mode: Above givens are x1, y1, w, h
)

data['artist'].each.with_index do |artist, i| 
	unless artist.nil?
		scale          = 1.0	
		render_color   = '#00000000'  # Any #XXXXXX00 (transparent)	
		# render_alpha = 0.0          # PNG alpha (transparent), if interpolating icons	
		render_width   = -1           # Disable wordwrap	
		render_height  = nil          # Necessary for text to overflow bottom edge	
		final_render   = false

		loop do
			if final_render == true             # Don't render drop shadow until final pass!
				# Drop Shadow
				text		str:       'Copyright © ' + artist,     
								x        copy_shadow_box.x1,     
								y        copy_shadow_box.y1,    
								width    copy_shadow_box.w,     
								height   copy_shadow_box.h,    
								align    'center',     
								valign   'middle',     
								font     copy_font,     
								font_size:	copy_size * scale,     
								color    'black',     
								ellipsize:	:none,     
								range    i
		  end
			e =   text str:		'Copyright © ' + artist,     
			           x        copy_box.x1,     
								 y        copy_box.y1,     
								 width    render_width,     
								 height   render_height,     
								 align    'center',     
								 valign   'middle',     
								 font     copy_font,     
								 font_size: copy_size * scale,     
								 color    render_color,     
								 ellipsize:	:none,     
								 range    i

		  if final_render == true then break end
			
			if copy_box.can_fit?(e[i][:width], e[i][:height])
				render_color  = copy_color		
				render_alpha  = 1.0		
				render_width  = copy_box.w		
				render_height	= copy_box.h		
				final_render  = true
			else
				scale *= scale_factor   # Even *= 0.99 has no noticeable delay                        # and results in exceptional fits
			end
    end # loop do
  end # unless artist.nil?
end # data['artist'].each.with_index do |artist, i|

##------------------END-COPYRIGHT-##

I know you can't see the exact implementation of my Box class and the can_fit method (but I'll be happy to send over all the code for my current project once it's in a mostly working and readable state, stay tuned!), but hopefully that all makes sense! It would be cool if there were a more convenient / built-in way to accomplish things like what I did above. I don't really have any idea what that would look like on your end, I'm just throwing it out there.

@bullno1
Copy link

bullno1 commented Mar 24, 2024

Is there a way to detect when this happens? I can manually override the font for specific cases but with a large number of cards I can't visually go through all of them.

@nickolasreynolds
Copy link

nickolasreynolds commented Mar 24, 2024

Is there a way to detect when this happens? I can manually override the font for specific cases but with a large number of cards I can't visually go through all of them.

In my sample code given above, note how I first set the dimensions of copy_box, the space I've provided on the card for one particular bit of rendered text. (In this case, the artist copyright declaration.)

Then, I invisibly render the text (color: '#00000000' has 00 alpha, it's fully transparent), saving the return values of the built in text command into the variable e: e = text. This return value is an "extent", that is, the coordinates and dimensions of the bounding rectangle of whatever Squib just rendered.

Lastly, I check that the rendered extent actually fits inside the space I set aside for it: copy_box.can_fit?(e[i][:width], e[i][:height]). (Though you can't see its code, can_fit? simply compares the dimensions of e to the dimensions of copy_box.) If e doesn't fit inside copy_box, then scale is reduced by scale_factor (relevant to the text command's parameter font_size: copy_size * scale), and I take another pass through the loop to try again. If it does fit, the (currently fully transparent) render color is set to the actual desired color (copy_color), the final_render flag is set to true, and I take one final pass through the loop to render everything one final time, this time visibly.

@bullno1
Copy link

bullno1 commented Mar 24, 2024

I vendorized and tried to patch squib: bullno1/LCI_Translation@509dec5#diff-0981dcc049afcbab0b08c40bec18f856affe3fae5b471e7d8b578c19eaaaed4e

It seems to work for my case.
If this seems ok, I can make a PR.

The idea is to just measure the box size during dummy draw.

@bullno1 bullno1 linked a pull request Mar 24, 2024 that will close this issue
5 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
Status: 📋 Backlog
Development

Successfully merging a pull request may close this issue.

3 participants