Source code for kqcircuits.util.label_polygons

# This code is part of KQCircuits
# Copyright (C) 2024 IQM Finland Oy
#
# This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public
# License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with this program. If not, see
# https://www.gnu.org/licenses/gpl-3.0.html.
#
# The software distribution should follow IQM trademark policy for open-source software
# (meetiqm.com/iqm-open-source-trademark-policy). IQM welcomes contributions to the code.
# Please see our contribution agreements for individuals (meetiqm.com/iqm-individual-contributor-license-agreement)
# and organizations (meetiqm.com/iqm-organization-contributor-license-agreement).

import logging
from functools import lru_cache
from pathlib import Path
from kqcircuits.pya_resolver import pya


# Expected properties of the text geometry as loaded from the ``font_polygons.oas`` file

# File path to the ``font_polygons.oas`` file
OAS_PATH = str(Path(__file__).parent.joinpath("font_polygons.oas"))
# Letters in the oas file
OAS_LETTERS = [chr(ord("A") + i) for i in range(0, 32)] + [chr(ord("0") + i) for i in range(0, 10)]
# Spacing between two letters
OAS_TEXT_SPACING = 300.0
# "mag" parameter set for TEXT pcell in oas file
OAS_TEXT_MAGNIFICATION = 500.0
# dbu in the oas file
OAS_DBU = 0.001


[docs] def get_text_polygon(label: str, size: int = OAS_TEXT_MAGNIFICATION) -> pya.Region: """Returns the given label string as a region. If size argument is given as non-integer, will round it to nearest micron. Utilizes speed ups compared to generating text geometry with KLayout's TEXT PCells. Only supports characters layed out in the ``font_polygons.oas`` file. """ font_polygons = load_font_polygons() unsported_characters = set(x.upper() for x in label) - set(font_polygons.keys()) - set(" ") if unsported_characters: logging.warning( f"Unsupported characters for get_text_polygon: {unsported_characters}." f" These characters will be skipped in label '{label}'" ) spacing = size * OAS_TEXT_SPACING / (OAS_DBU * OAS_TEXT_MAGNIFICATION) label_region = pya.Region() if label is not None: for i, letter in enumerate(str(label)): if letter.upper() not in font_polygons: continue label_region += ( font_polygons[letter.upper()] .scaled_and_snapped(0, round(size), OAS_TEXT_MAGNIFICATION, 0, round(size), OAS_TEXT_MAGNIFICATION) .moved(i * spacing, 0) ) return label_region
[docs] @lru_cache(maxsize=None) def load_font_polygons() -> dict[str, pya.Region]: """Loads from static OAS file a region for each letter used in labels. Cached for reuse. """ layout = pya.Layout() layout.read(OAS_PATH) font_dict = {letter: pya.Region() for letter in OAS_LETTERS} for shape in pya.Region(layout.top_cells()[-1].begin_shapes_rec(layout.layer(129, 1))).each(): index = round(shape.bbox().to_dtype(OAS_DBU).p1.x) // OAS_TEXT_MAGNIFICATION font_dict[OAS_LETTERS[int(index)]] += pya.Region(shape.moved(-OAS_TEXT_MAGNIFICATION * index / OAS_DBU, 0)) return font_dict