Aurigma Forums
 » 
Graphics Mill
 » 
Discussions – Graphics Mill
 » 
What is the best way to know the font size that will result in a specific BlackBox?
 
		
        
            
            
	
    | 
Rank: Member
 Groups: Guest
Joined: 1/10/2016(UTC)
 Posts: 15
 
 Thanks: 7 times
 | 
            
	      
                I'm trying to write program using GraphicsMill that will generate a PDF with a specific size. What is the best way to draw an ArtText that will fill the maximum area available as possible without having to stretch it? I'm trying to guess what is the best font size doing an exhaustive search for the font size starting on 1. That's not efficient at all and can take a lot of time depending on the target size. Do you have something to recommend? Code:
Imports Aurigma.GraphicsMill
Imports Aurigma.GraphicsMill.AdvancedDrawing
Imports Aurigma.GraphicsMill.AdvancedDrawing.Art
Imports Aurigma.GraphicsMill.AdvancedDrawing.Effects
Imports Aurigma.GraphicsMill.Codecs
Imports DPointF = System.Drawing.PointF
Imports DRectangleF = System.Drawing.RectangleF
   (...)
    Private Shared Sub UpdateFontSize(options As WarpedTextOptions, graphics As Graphics, targetRect As DRectangleF)
        Dim unionBlackbox As New DRectangleF
        Dim targetRectPixels As New DRectangleF(
                    UnitConverter.ConvertUnitsToPixels(options.DPI, targetRect.X, Unit.Point),
                    UnitConverter.ConvertUnitsToPixels(options.DPI, targetRect.Y, Unit.Point),
                    UnitConverter.ConvertUnitsToPixels(options.DPI, targetRect.Width, Unit.Point),
                    UnitConverter.ConvertUnitsToPixels(options.DPI, targetRect.Height, Unit.Point))
        options.TextFontSize = 1
        Do
            options.TextFontSize = options.TextFontSize + 1
            Dim artText = GetArtText(options, graphics)
            Dim textBlackBox = artText.GetBlackBox()
            Dim shadowBlackbox As New DRectangleF(textBlackBox.Location, textBlackBox.Size)
            shadowBlackbox.Inflate(options.Shadow.SizePixels, options.Shadow.SizePixels)
            shadowBlackbox.Offset(options.Shadow.OffsetXPixels, options.Shadow.OffsetYPixels)
            unionBlackbox = DRectangleF.Union(textBlackBox, shadowBlackbox)
        Loop While unionBlackbox.Width < targetRectPixels.Width AndAlso unionBlackbox.Height < targetRectPixels.Height
        options.TextFontSize = options.TextFontSize - 1
    End Sub
   (...)
 | 
	
    | 
             | 
            
         | 
    |  | 
        
        
        
         
		   
        
            
            
	
    | 
Rank: Member
 Groups: Guest
Joined: 1/10/2016(UTC)
 Posts: 15
 
 Thanks: 7 times
 | 
            
	      
                As suggested by a friend of mine, I refactored the code to use binary search, that increased the performance from seconds to milliseconds. Does anyone see any problem on using the max value as the targetRect height. Code:
Imports Aurigma.GraphicsMill
Imports Aurigma.GraphicsMill.AdvancedDrawing
Imports Aurigma.GraphicsMill.AdvancedDrawing.Art
Imports Aurigma.GraphicsMill.AdvancedDrawing.Effects
Imports Aurigma.GraphicsMill.Codecs
Imports DPointF = System.Drawing.PointF
Imports DRectangleF = System.Drawing.RectangleF
   (...)
    Private Shared Sub UpdateFontSize(
        options As WarpedTextOptions, graphics As Graphics, targetRect As DRectangleF)
        Dim unionBlackbox As New DRectangleF
        Dim targetRectPixels As New DRectangleF(
                    UnitConverter.ConvertUnitsToPixels(options.DPI, targetRect.X, Unit.Point),
                    UnitConverter.ConvertUnitsToPixels(options.DPI, targetRect.Y, Unit.Point),
                    UnitConverter.ConvertUnitsToPixels(options.DPI, targetRect.Width, Unit.Point),
                    UnitConverter.ConvertUnitsToPixels(options.DPI, targetRect.Height, Unit.Point))
        Dim min = MIN_FONT_SIZE
        Dim max = targetRect.Height
        options.TextFontSize = min
        While min < max
            Dim mid As Integer = CInt((min + max) / 2)
            options.TextFontSize = mid
            Dim artText = GetArtText(options, graphics)
            Dim textBlackBox = artText.GetBlackBox()
            Dim shadowBlackbox As New DRectangleF(textBlackBox.Location, textBlackBox.Size)
            shadowBlackbox.Inflate(options.Shadow.SizePixels, options.Shadow.SizePixels)
            shadowBlackbox.Offset(options.Shadow.OffsetXPixels, options.Shadow.OffsetYPixels)
            unionBlackbox = DRectangleF.Union(textBlackBox, shadowBlackbox)
            If (unionBlackbox.Width < targetRectPixels.Width AndAlso
                unionBlackbox.Height < targetRectPixels.Height) Then
                min = mid + 1
            Else
                max = mid - 1
            End If
        End While
    End Sub
   (...)
 Edited by user Tuesday, August 30, 2016 4:11:31 PM(UTC)
 | Reason: typo | 
	
    | 
             | 
            
         | 
    |  | 
        
        
        
    
		
        
            
            
	
    | 
Rank: Advanced Member
 Groups: Guest
Joined: 7/28/2003(UTC)
 Posts: 1,660
 
 Thanks: 5 timesWas thanked: 76 time(s) in 74 post(s)
 
 | 
            
	      
                Hi, Here is my code review.  Code:	Private Shared Sub UpdateFontSize(
		options As WarpedTextOptions, graphics As Graphics, targetRect As DRectangleF)
		Dim unionBlackbox As New DRectangleF
		Dim targetRectPixels As New DRectangleF(
					UnitConverter.ConvertUnitsToPixels(options.DPI, targetRect.X, Unit.Point),
					UnitConverter.ConvertUnitsToPixels(options.DPI, targetRect.Y, Unit.Point),
					UnitConverter.ConvertUnitsToPixels(options.DPI, targetRect.Width, Unit.Point),
					UnitConverter.ConvertUnitsToPixels(options.DPI, targetRect.Height, Unit.Point))
		'Dim min = MIN_FONT_SIZE
		' 1. The maximum size of inscribed figure is a diagonal of a rectangle
		' 2. Use a font size of the float (Single) type. Otherwise you can get an inaccurate result
		Dim max As Single = System.Math.Sqrt(targetRect.Height * targetRect.Height + targetRect.Width * targetRect.Width)
		'Dim max = targetRect.Height
		Dim max As Single = targetRect.Height
		'options.TextFontSize = min
		' 3. Limit an iteration count to prevent hanging
		Const MAX_ITERATIONS As Integer = 20
		Dim i = 0
		'While min < max
		' 4. Use a condition based on precison
		Const PRECISION As Single = 0.05F
		While (max - min) / max > PRECISION AndAlso i < MAX_ITERATIONS
			' Dim mid As Integer = CInt((min + max) / 2)
			' See p. 2
			Dim mid As Single = CSng((min + max) / 2.0F)
			options.TextFontSize = mid
			Dim artText = GetArtText(options, graphics)
			Dim textBlackBox = artText.GetBlackBox()
			Dim shadowBlackbox As New DRectangleF(textBlackBox.Location, textBlackBox.Size)
			shadowBlackbox.Inflate(options.Shadow.SizePixels, options.Shadow.SizePixels)
			shadowBlackbox.Offset(options.Shadow.OffsetXPixels, options.Shadow.OffsetYPixels)
			unionBlackbox = DRectangleF.Union(textBlackBox, shadowBlackbox)
			' 5. There is no need to increment/decrement the mid value:
			If (unionBlackbox.Width < targetRectPixels.Width AndAlso
				unionBlackbox.Height < targetRectPixels.Height) Then
				'min = mid + 1
				min = mid
			Else
				'max = mid - 1
				max = mid
			End If
			i = i + 1
		End While
	End Sub
 Please be advised that the code is untested. Edited by user Wednesday, August 31, 2016 3:30:18 AM(UTC)
 | Reason: Not specified | 
| Best regards, Fedor Skvortsov
 | 
	
    | 
              1 user thanked Fedor for this useful post. |  | 
    |  | 
        
        
        
         
		   
        
            
            
	
    | 
Rank: Member
 Groups: Guest
Joined: 1/10/2016(UTC)
 Posts: 15
 
 Thanks: 7 times
 | 
            
	      
                Hi Fedor, why the max font size should be the max size of the inscribed figure (diagonal)? | 
	
    | 
             | 
            
         | 
    |  | 
        
        
        
    
		
        
            
            
	
    | 
Rank: Advanced Member
 Groups: Guest
Joined: 7/28/2003(UTC)
 Posts: 1,660
 
 Thanks: 5 timesWas thanked: 76 time(s) in 74 post(s)
 
 | 
            
	      
                Please see the attached image:  | 
| Best regards, Fedor Skvortsov
 | 
	
    | 
             | 
            
         | 
    |  | 
        
        
        
    
Aurigma Forums
 » 
Graphics Mill
 » 
Discussions – Graphics Mill
 » 
What is the best way to know the font size that will result in a specific BlackBox?
 
    
        Forum Jump
         
    
    You cannot post new topics in this forum.
You cannot reply to topics in this forum.
You cannot delete your posts in this forum.
You cannot edit your posts in this forum.
You cannot create polls in this forum.
You cannot vote in polls in this forum.