class RenderSide: # On the sides, we only have component outlines and component text def __init__(self) -> None: self.va_outlines = VA_xy(1024) self.va_text = VA_tex(1024) def clear(self) -> None: self.va_outlines.clear() self.va_text.clear() def extend(self, other: 'RenderSide') -> None: self.va_outlines.extend(other.va_outlines) self.va_text.extend(other.va_text)
class RenderVia: # Multilayer, we only have vias, and pin labels def __init__(self) -> None: self.va_vias = VA_via(1024) self.va_text = VA_tex(1024) def clear(self) -> None: self.va_vias.clear() self.va_text.clear() def extend(self, other: 'RenderVia') -> None: self.va_vias.extend(other.va_vias) self.va_text.extend(other.va_text)
class RenderPCBLayer: # PCB layers have traces, text def __init__(self) -> None: self.va_traces = VA_thickline(1024) self.va_text = VA_tex(1024) def clear(self) -> None: self.va_traces.clear() self.va_text.clear() def extend(self, other: 'RenderPCBLayer') -> None: self.va_traces.extend(other.va_traces) self.va_text.extend(other.va_text)
class TextBatcher: _render_tag = namedtuple("_render_tag", ["textinfo", "matrix", "color"]) def __init__(self, tr: 'TextRender') -> None: self.text_render = tr self.__cached: Dict[str, '_StringMetrics'] = {} self._va = VA_tex(1024) self.restart() def restart(self) -> None: self.__render_tags: Dict[ Any, List['TextBatcher._render_tag']] = defaultdict(list) self._va.clear() def initializeGL(self) -> None: # Working VBO that will contain glyph data self.vbo = VBO(numpy.ndarray([], dtype=self.text_render.buffer_dtype), GL.GL_DYNAMIC_DRAW, GL.GL_ARRAY_BUFFER) self.vao = VAO() with self.vao, self.vbo: self.text_render.b1.assign() self.text_render.b2.assign() self.__vbo_needs_update = True def render(self, key: Any = None) -> None: return if self.__vbo_needs_update: self.vbo.data = self._va.buffer()[:] self.vbo.bind() self.__vbo_needs_update = False self.text_render.updateTexture() with self.text_render.sdf_shader.program, self.text_render.tex.on( GL.GL_TEXTURE_2D), self.vao: GL.glUniform1i(self.text_render.sdf_shader.program.uniforms.tex1, 0) GL.glUniform4ui(self.text_render.sdf_shader.uniforms.layer_info, 255, COL_TEXT, 0, 255) for tag in self.__render_tags[key]: mat_calc = tag.matrix GL.glUniformMatrix3fv(self.text_render.sdf_shader.uniforms.mat, 1, True, mat_calc.astype(numpy.float32)) GL.glDrawArrays(GL.GL_TRIANGLES, tag.textinfo.start, tag.textinfo.count) def submit(self, ts: '_StringMetrics', mat: 'npt.NDArray[numpy.float64]', color: Any, k: Any = None) -> None: self.__render_tags[k].append(self._render_tag(ts, mat, color)) def submit_text_box(self, premat: 'npt.NDArray[numpy.float64]', text: str, box: Rect, color: Any, k: Any = None) -> None: ts = self.get_string(text) mat = premat.dot(ts.get_render_to_mat(box)) self.submit(ts, mat, color, k) def get_string(self, text: str) -> '_StringMetrics': if text in self.__cached: return self.__cached[text] self.__cached[text] = ti = self.text_render.getStringMetrics(text) ti.start = self._va.tell() self._va.extend(ti.arr) ti.count = ti.arr.count() self.__vbo_needs_update = True return ti