{"id":28454650,"url":"https://github.com/mlight-lee/shx-parser","last_synced_at":"2025-08-21T10:11:23.571Z","repository":{"id":293626076,"uuid":"984619350","full_name":"mlight-lee/shx-parser","owner":"mlight-lee","description":"A TypeScript library for parsing AutoCAD SHX font files","archived":false,"fork":false,"pushed_at":"2025-06-06T03:12:23.000Z","size":154,"stargazers_count":23,"open_issues_count":1,"forks_count":2,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-08-03T15:10:11.649Z","etag":null,"topics":["autocad","dwg","dxf","dxf-reader","dxf-writer","shx","shx-font"],"latest_commit_sha":null,"homepage":"https://mlight-lee.github.io/shx-parser/","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/mlight-lee.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-05-16T08:20:25.000Z","updated_at":"2025-08-03T11:42:18.000Z","dependencies_parsed_at":"2025-05-16T09:57:54.607Z","dependency_job_id":null,"html_url":"https://github.com/mlight-lee/shx-parser","commit_stats":null,"previous_names":["mlight-lee/shx-parser"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/mlight-lee/shx-parser","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlight-lee%2Fshx-parser","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlight-lee%2Fshx-parser/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlight-lee%2Fshx-parser/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlight-lee%2Fshx-parser/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/mlight-lee","download_url":"https://codeload.github.com/mlight-lee/shx-parser/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/mlight-lee%2Fshx-parser/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":271462071,"owners_count":24763857,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-21T02:00:08.990Z","response_time":74,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["autocad","dwg","dxf","dxf-reader","dxf-writer","shx","shx-font"],"created_at":"2025-06-06T19:43:50.901Z","updated_at":"2025-08-21T10:11:23.566Z","avatar_url":"https://github.com/mlight-lee.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SHX Parser\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n[![npm version](https://badge.fury.io/js/@mlightcad%2Fshx-parser.svg)](https://badge.fury.io/js/@mlightcad/shx-parser)\n[![CI/CD](https://github.com/shx-parser/shx-parser/actions/workflows/ci-cd.yml/badge.svg)](https://github.com/shx-parser/shx-parser/actions/workflows/ci-cd.yml)\n\nA TypeScript library for parsing AutoCAD SHX font files. It is ported from [this project](https://github.com/yzylovepmn/YFonts.SHX) written by C#. This project fixed many bugs on the original parser. Moreover, support parsing [extended big font](https://help.autodesk.com/view/OARX/2023/ENU/?guid=GUID-00ED0CC6-A4BE-4591-93FA-598CC40AA43D).\n\nIf you are interested in the format of SHX font, please refer to [this document](https://help.autodesk.com/view/OARX/2023/ENU/?guid=GUID-06832147-16BE-4A66-A6D0-3ADF98DC8228).\n\n## Features\n\n- Parse SHX font files and extract font data\n- Support for various SHX font types:\n  - Shapes\n  - Bigfont (including Extended Big Font)\n  - Unifont\n- Shape parsing with performance optimization:\n  - On-demand parsing\n  - Shape caching by character code and size\n- Modern TypeScript implementation\n- Object-oriented design\n- Comprehensive test coverage\n\n## Installation\n\nUsing npm:\n```bash\nnpm install @mlightcad/shx-parser\n```\n\nUsing pnpm:\n```bash\npnpm add @mlightcad/shx-parser\n```\n\nUsing yarn:\n```bash\nyarn add @mlightcad/shx-parser\n```\n\n## Demo app\n\nThe [demo app](https://mlight-lee.github.io/shx-parser/) is provided with a web-based interface for viewing and exploring SHX font files with the following features:\n\n- **Dual Loading Modes**:\n  - Upload local SHX files\n  - Select from a remote font library\n\n- **Main Features**:\n  - View all characters in a responsive grid layout\n  - Search characters by code (decimal/hex)\n  - Click characters to see them in a larger modal view\n  - Toggle between decimal and hexadecimal code display\n\n- **Display Information**:\n  - Shows font type, version, and character count\n  - Renders characters as SVG graphics\n  - Responsive grid layout that works on different screen sizes\n\n\n## Quick Start\n\n```typescript\nimport { ShxFont } from '@mlightcad/shx-parser';\n\n// Load the font file\nconst fontFileData = /* ArrayBuffer containing SHX font file data */;\nconst font = new ShxFont(fontFileData);\n\n// Get shape for a character\nconst charCode = 65; // ASCII code for 'A'\nconst fontSize = 12;\nconst shape = font.getCharShape(charCode, fontSize);\n\nif (shape) {\n  console.log(shape.polylines); // Array of polylines representing the character\n  console.log(shape.lastPoint); // End point of the character\n}\n\n// Clean up resources when done\nfont.release();\n```\n\n## API Documentation\n\n### `ShxFont`\n\nThe main class for working with SHX fonts.\n\n```typescript\nclass ShxFont {\n  fontData: ShxFontData;\n  constructor(data: ArrayBuffer);\n  getCharShape(charCode: number, size: number): ShxShape | null;\n  release(): void;\n}\n```\n\n### `ShxShape`\n\nRepresents a parsed character shape.\n\n```typescript\ninterface ShxShape {\n  polylines: Array\u003c{ x: number; y: number }[]\u003e;  // Array of polyline points\n  lastPoint: { x: number; y: number };           // End point of the shape\n}\n```\n\n### Font Data Structure\n\nThe library parses SHX font files into the following structure:\n\n```typescript\ninterface ShxFontData {\n  header: {\n    fontType: ShxFontType;     // 'shapes' | 'bigfont' | 'unifont'\n    fileHeader: string;        // Font file header information\n    fileVersion: string;       // Font file version\n  };\n  content: {\n    data: Record\u003cnumber, Uint8Array\u003e;  // Character code to bitmap data mapping\n    info: string;              // Additional font information\n    orientation: string;       // Text orientation ('horizontal' | 'vertical')\n    baseUp: number;            // Pixels above baseline\n    baseDown: number;          // Pixels below baseline\n    isExtended: boolean;       // Flag to indicate if the font is an extended big font\n  };\n}\n```\n\n## Example\n\n### Loading and Displaying Font Information\n\n```typescript\nimport { readFile } from 'fs/promises';\nimport { ShxFont } from '@mlightcad/shx-parser';\n\nasync function loadFont(filePath: string) {\n  const buffer = await readFile(filePath);\n  const font = new ShxFont(buffer.buffer);\n  \n  // Display font information\n  const fontData = font.fontData;\n  console.log('Font Information:');\n  console.log('----------------');\n  console.log('Font Type:', fontData.header.fontType);\n  console.log('Header:', fontData.header.fileHeader);\n  console.log('Version:', fontData.header.fileVersion);\n  console.log('Info:', fontData.content.info);\n  console.log('Orientation:', fontData.content.orientation);\n  console.log('Base Up:', fontData.content.baseUp);\n  console.log('Base Down:', fontData.content.baseDown);\n  console.log('Number of shapes:', Object.keys(fontData.content.data).length);\n  \n  return font;\n}\n```\n\n### Converting Shape to SVG Path\n\n```typescript\nfunction shapeToSvgPath(shape: ShxShape, x: number = 0, y: number = 0): string {\n  if (!shape?.polylines.length) return '';\n  \n  return shape.polylines.map(polyline =\u003e {\n    if (!Array.isArray(polyline) || polyline.length === 0) return '';\n    \n    return polyline.map((point, i) =\u003e {\n      const scaledX = (Number(point.x) || 0) + x;\n      const scaledY = -(Number(point.y) || 0) + y; // Flip Y coordinate for SVG\n      const command = i === 0 ? 'M' : 'L';\n      return `${command} ${scaledX.toFixed(2)} ${scaledY.toFixed(2)}`;\n    }).join(' ');\n  }).filter(Boolean).join(' ');\n}\n```\n\n### Rendering Text to SVG\n\n```typescript\ninterface SvgOptions {\n  width?: number;\n  height?: number;\n  strokeWidth?: string;\n  strokeColor?: string;\n  isAutoFit?: boolean;\n}\n\nfunction renderTextToSvg(\n  font: ShxFont, \n  text: string, \n  size: number, \n  options: SvgOptions = {}\n): SVGElement {\n  const {\n    width = 1000,\n    height = 1000,\n    strokeWidth = '0.1%',\n    strokeColor = 'black',\n    isAutoFit = false\n  } = options;\n\n  // Create SVG element\n  const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');\n  svg.setAttribute('width', width.toString());\n  svg.setAttribute('height', height.toString());\n  svg.setAttribute('viewBox', `0 0 ${width} ${height}`);\n\n  const padding = size;\n  let currentX = padding;\n  let maxHeight = 0;\n\n  // Process each character\n  for (const char of text) {\n    const charCode = char.charCodeAt(0);\n    const shape = font.getCharShape(charCode, size);\n    \n    if (shape) {\n      const group = document.createElementNS('http://www.w3.org/2000/svg', 'g');\n      \n      if (isAutoFit) {\n        // Auto-fit positioning\n        const bbox = shape.bbox;\n        const padding = 0.2; // 20% padding\n        const width = bbox.maxX - bbox.minX;\n        const height = bbox.maxY - bbox.minY;\n        const centerX = (bbox.minX + bbox.maxX) / 2;\n        const centerY = (bbox.minY + bbox.maxY) / 2;\n        group.setAttribute('transform', `translate(${currentX - centerX}, ${-centerY})`);\n      } else {\n        // Fixed positioning\n        group.setAttribute('transform', `translate(${currentX + width / 2}, ${height / 2})`);\n      }\n\n      // Create path for the character\n      const pathData = shapeToSvgPath(shape);\n      const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');\n      path.setAttribute('d', pathData);\n      path.setAttribute('fill', 'none');\n      path.setAttribute('stroke', strokeColor);\n      path.setAttribute('stroke-width', strokeWidth);\n      \n      group.appendChild(path);\n      svg.appendChild(group);\n\n      // Update position for next character\n      if (shape.lastPoint) {\n        currentX += shape.lastPoint.x + size * 0.5;\n      } else {\n        currentX += size;\n      }\n      \n      maxHeight = Math.max(maxHeight, size);\n    }\n  }\n\n  return svg;\n}\n\n// Example usage:\nasync function main() {\n  try {\n    const font = await loadFont('path/to/your/font.shx');\n    \n    // Example 1: Basic rendering\n    const svgElement1 = renderTextToSvg(font, \"Hello\", 12);\n    document.body.appendChild(svgElement1);\n    \n    // Example 2: Auto-fit rendering with custom options\n    const svgElement2 = renderTextToSvg(font, \"Hello\", 12, {\n      width: 1000,\n      height: 1000,\n      strokeWidth: '0.1%',\n      strokeColor: 'black',\n      isAutoFit: true\n    });\n    document.body.appendChild(svgElement2);\n    \n    // Clean up resources when done\n    font.release();\n  } catch (error) {\n    console.error('Error:', error instanceof Error ? error.message : 'An unknown error occurred');\n  }\n}\n```\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request. For major changes, please open an issue first to discuss what you would like to change.\n\n1. Fork the repository\n2. Create your feature branch (`git checkout -b feature/amazing-feature`)\n3. Commit your changes (`git commit -m 'Add some amazing feature'`)\n4. Push to the branch (`git push origin feature/amazing-feature`)\n5. Open a Pull Request\n\nPlease make sure to update tests as appropriate.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Support\n\nIf you have any questions or run into issues, please:\n1. Check the [GitHub Issues](https://github.com/shx-parser/shx-parser/issues) page\n2. Open a new issue if your problem hasn't been reported yet\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmlight-lee%2Fshx-parser","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmlight-lee%2Fshx-parser","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmlight-lee%2Fshx-parser/lists"}