@@ -35,6 +35,7 @@ function loadInitialData() {
3535
3636 // Update full string after setting initial values
3737 updateFullString ( ) ;
38+ drawBadge ( ) ; // Add this line
3839}
3940
4041// Call loadInitialData when the page loads
@@ -43,6 +44,12 @@ window.addEventListener('load', loadInitialData);
4344const inputs = document . querySelectorAll ( 'input:not(#fullstring)' ) ;
4445const fullStringInput = document . getElementById ( 'fullstring' ) ;
4546const qrcodeContainer = document . getElementById ( 'qrcode' ) ;
47+ const canvas = document . getElementById ( 'badgeCanvas' ) ;
48+ const ctx = canvas . getContext ( '2d' ) ;
49+
50+ // Add this near the top of the file with other constants
51+ const backgroundImage = new Image ( ) ;
52+ backgroundImage . src = './back.png' ;
4653
4754function updateFullString ( ) {
4855 const id = '01234567890' ; // Static ID for this example
@@ -66,6 +73,7 @@ function updateFullString() {
6673 // Join the values and create the full string
6774 fullStringInput . value = `${ id } iD^${ orderedValues . join ( '^' ) } ^` ;
6875 generateQRCode ( ) ;
76+ drawBadge ( ) ; // Add this line
6977}
7078
7179function generateQRCode ( ) {
@@ -97,13 +105,18 @@ async function fetchGitHubUser(username) {
97105 }
98106}
99107
108+ // Add this helper function before updateFormWithGitHubData
109+ function cleanJobTitle ( title ) {
110+ return title . replace ( / \s * @ \w + $ / , '' ) . trim ( ) ;
111+ }
112+
100113// Function to update form fields with GitHub data
101114function updateFormWithGitHubData ( data ) {
102115 if ( data ) {
103116 document . getElementById ( 'firstname' ) . value = data . name ? data . name . split ( ' ' ) [ 0 ] : '' ;
104117 document . getElementById ( 'lastname' ) . value = data . name ? data . name . split ( ' ' ) . slice ( 1 ) . join ( ' ' ) : '' ;
105118 document . getElementById ( 'company' ) . value = data . company ? data . company . replace ( / ^ @ / , '' ) : '' ;
106- document . getElementById ( 'jobtitle' ) . value = data . bio ? data . bio . split ( '.' ) [ 0 ] . trim ( ) : '' ;
119+ document . getElementById ( 'jobtitle' ) . value = data . bio ? cleanJobTitle ( data . bio . split ( '.' ) [ 0 ] . trim ( ) ) : '' ;
107120 updateFullString ( ) ; // Update the full string with new data
108121 }
109122}
@@ -122,8 +135,14 @@ const githubHandleInput = document.getElementById('githubhandle');
122135githubHandleInput . addEventListener ( 'input' , handleGitHubInput ) ;
123136githubHandleInput . addEventListener ( 'blur' , handleGitHubInput ) ;
124137
138+ // Modify the input event listeners to clean job titles
125139inputs . forEach ( input => {
126- input . addEventListener ( 'input' , updateFullString ) ;
140+ input . addEventListener ( 'input' , ( e ) => {
141+ if ( e . target . id === 'jobtitle' ) {
142+ e . target . value = cleanJobTitle ( e . target . value ) ;
143+ }
144+ updateFullString ( ) ;
145+ } ) ;
127146} ) ;
128147
129148updateFullString ( ) ; // Initial generation
@@ -166,3 +185,141 @@ fullStringInput.addEventListener('keydown', (event) => {
166185 updateFieldsFromFullString ( ) ;
167186 }
168187} ) ;
188+
189+ // Modify the drawBadge function
190+ function drawBadge ( ) {
191+ // Enable crisp font rendering
192+ ctx . textRendering = 'optimizeLegibility' ;
193+ ctx . imageSmoothingEnabled = false ;
194+ ctx . antialias = 'none' ;
195+
196+ const bottomMargin = 10 ;
197+ const leftMargin = 10 ;
198+ const topMargin = 10 ;
199+
200+ ctx . drawImage ( backgroundImage , 0 , 0 , canvas . width , canvas . height ) ;
201+ ctx . textBaseline = 'top' ;
202+
203+ // Draw first name in bold
204+ ctx . font = 'bold 32px "Mona Sans"' ;
205+ ctx . fillStyle = '#000000' ;
206+ const firstname = document . getElementById ( 'firstname' ) . value ;
207+ ctx . fillText ( firstname , leftMargin , topMargin ) ;
208+
209+ // Draw last name in bold
210+ ctx . font = 'bold 24px "Mona Sans"' ;
211+ const lastname = document . getElementById ( 'lastname' ) . value ;
212+ ctx . fillText ( lastname , leftMargin , 45 ) ;
213+
214+ // Calculate dynamic font size for job title
215+ const jobtitle = document . getElementById ( 'jobtitle' ) . value ;
216+ let jobtitleFontSize = 14 ;
217+ ctx . font = `${ jobtitleFontSize } px "Mona Sans"` ;
218+ while ( ctx . measureText ( jobtitle ) . width > canvas . width - 40 && jobtitleFontSize > 8 ) {
219+ jobtitleFontSize -- ;
220+ ctx . font = `${ jobtitleFontSize } px "Mona Sans"` ;
221+ }
222+
223+ // Get GitHub handle
224+ let githubhandle = document . getElementById ( 'githubhandle' ) . value ;
225+ if ( githubhandle && ! githubhandle . startsWith ( '@' ) ) {
226+ githubhandle = '@' + githubhandle ;
227+ }
228+
229+ // Calculate text metrics to fit job title within canvas
230+ ctx . font = `${ jobtitleFontSize } px "Mona Sans"` ;
231+ const fontMetrics = ctx . measureText ( jobtitle ) ;
232+ const textHeight = fontMetrics . actualBoundingBoxAscent + fontMetrics . actualBoundingBoxDescent ;
233+ const lineHeightGap = textHeight * 0.5 ;
234+
235+ const githubHandleY = ( canvas . height ) - bottomMargin - textHeight ;
236+ const jobTitleY = githubHandleY - textHeight - lineHeightGap ;
237+
238+ // Draw the text
239+ ctx . fillText ( jobtitle , leftMargin , jobTitleY ) ;
240+ ctx . fillText ( githubhandle , leftMargin , githubHandleY ) ;
241+ }
242+
243+ // Replace the font loading with combined font and image loading
244+ Promise . all ( [
245+ document . fonts . ready ,
246+ new Promise ( resolve => backgroundImage . onload = resolve )
247+ ] ) . then ( ( ) => {
248+ drawBadge ( ) ;
249+ } ) ;
250+
251+ // Update the event listener to handle resize
252+ window . addEventListener ( 'resize' , drawBadge ) ;
253+
254+ // Add this function to convert image data to 2-bit black and white
255+ function convertTo2BitBW ( imageData ) {
256+ const threshold = 128 ;
257+ const newCanvas = document . createElement ( 'canvas' ) ;
258+ newCanvas . width = imageData . width ;
259+ newCanvas . height = imageData . height ;
260+ const ctx = newCanvas . getContext ( '2d' ) ;
261+
262+ // Create new imageData
263+ const newImageData = ctx . createImageData ( imageData . width , imageData . height ) ;
264+
265+ for ( let i = 0 ; i < imageData . data . length ; i += 4 ) {
266+ // Convert to grayscale first
267+ const gray = ( imageData . data [ i ] * 0.299 +
268+ imageData . data [ i + 1 ] * 0.587 +
269+ imageData . data [ i + 2 ] * 0.114 ) ;
270+
271+ // Convert to black or white (2-bit)
272+ const bw = gray < threshold ? 0 : 255 ;
273+
274+ newImageData . data [ i ] = bw ; // R
275+ newImageData . data [ i + 1 ] = bw ; // G
276+ newImageData . data [ i + 2 ] = bw ; // B
277+ newImageData . data [ i + 3 ] = 255 ; // A
278+ }
279+
280+ ctx . putImageData ( newImageData , 0 , 0 ) ;
281+ return newCanvas ;
282+ }
283+
284+ // Modify the downloadBadge function to use the conversion
285+ function downloadBadge ( ) {
286+ const canvas = document . getElementById ( 'badgeCanvas' ) ;
287+ const ctx = canvas . getContext ( '2d' ) ;
288+ const imageData = ctx . getImageData ( 0 , 0 , canvas . width , canvas . height ) ;
289+
290+ // Convert to 2-bit black and white
291+ const bwCanvas = convertTo2BitBW ( imageData ) ;
292+
293+ const link = document . createElement ( 'a' ) ;
294+ link . download = 'badge.png' ;
295+ link . href = bwCanvas . toDataURL ( 'image/png' ) ;
296+ link . click ( ) ;
297+ }
298+
299+ // Add this function at the end of the file
300+ function downloadPythonCode ( ) {
301+ const pythonCode = `import badger2040
302+ import pngdec
303+ import time, os
304+
305+ display = badger2040.Badger2040()
306+ png = pngdec.PNG(display.display)
307+
308+ display.led(128)
309+ display.clear()
310+
311+ try:
312+ png.open_file("badge.png")
313+ png.decode()
314+ except (OSError, RuntimeError):
315+ print("Badge background error")
316+
317+ display.update()` ;
318+
319+ const blob = new Blob ( [ pythonCode ] , { type : 'text/plain' } ) ;
320+ const link = document . createElement ( 'a' ) ;
321+ link . download = 'main.py' ;
322+ link . href = URL . createObjectURL ( blob ) ;
323+ link . click ( ) ;
324+ URL . revokeObjectURL ( link . href ) ;
325+ }
0 commit comments