From 2d8e86324b703b2a8f88b9da09f9ef3d02724af3 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 24 Mar 2025 20:07:21 +1100 Subject: [PATCH 1/7] [gt911][cst226][ektf2232] Swap x and y calibration values (#8450) Co-authored-by: Keith Burzinski --- .../cst226/touchscreen/cst226_touchscreen.cpp | 2 ++ .../ektf2232/touchscreen/ektf2232.cpp | 35 ++++++++++--------- .../gt911/touchscreen/gt911_touchscreen.cpp | 19 ++++++---- 3 files changed, 33 insertions(+), 23 deletions(-) diff --git a/esphome/components/cst226/touchscreen/cst226_touchscreen.cpp b/esphome/components/cst226/touchscreen/cst226_touchscreen.cpp index d4e43d30f5..a25859fe17 100644 --- a/esphome/components/cst226/touchscreen/cst226_touchscreen.cpp +++ b/esphome/components/cst226/touchscreen/cst226_touchscreen.cpp @@ -72,6 +72,8 @@ void CST226Touchscreen::continue_setup_() { if (this->read16_(0xD1F8, buffer, 4)) { this->x_raw_max_ = buffer[0] + (buffer[1] << 8); this->y_raw_max_ = buffer[2] + (buffer[3] << 8); + if (this->swap_x_y_) + std::swap(this->x_raw_max_, this->y_raw_max_); } else { this->x_raw_max_ = this->display_->get_native_width(); this->y_raw_max_ = this->display_->get_native_height(); diff --git a/esphome/components/ektf2232/touchscreen/ektf2232.cpp b/esphome/components/ektf2232/touchscreen/ektf2232.cpp index ef8f1c6802..603b554273 100644 --- a/esphome/components/ektf2232/touchscreen/ektf2232.cpp +++ b/esphome/components/ektf2232/touchscreen/ektf2232.cpp @@ -34,26 +34,29 @@ void EKTF2232Touchscreen::setup() { // Get touch resolution uint8_t received[4]; - if (this->x_raw_max_ == this->x_raw_min_) { - this->write(GET_X_RES, 4); - if (this->read(received, 4)) { - ESP_LOGE(TAG, "Failed to read X resolution!"); + if (this->x_raw_max_ == 0 || this->y_raw_max_ == 0) { + auto err = this->write(GET_X_RES, 4); + if (err == i2c::ERROR_OK) { + err = this->read(received, 4); + if (err == i2c::ERROR_OK) { + this->x_raw_max_ = ((received[2])) | ((received[3] & 0xf0) << 4); + err = this->write(GET_Y_RES, 4); + if (err == i2c::ERROR_OK) { + err = this->read(received, 4); + if (err == i2c::ERROR_OK) { + this->y_raw_max_ = ((received[2])) | ((received[3] & 0xf0) << 4); + } + } + } + } + if (err != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Failed to read calibration values!"); this->interrupt_pin_->detach_interrupt(); this->mark_failed(); return; } - this->x_raw_max_ = ((received[2])) | ((received[3] & 0xf0) << 4); - } - - if (this->y_raw_max_ == this->y_raw_min_) { - this->write(GET_Y_RES, 4); - if (this->read(received, 4)) { - ESP_LOGE(TAG, "Failed to read Y resolution!"); - this->interrupt_pin_->detach_interrupt(); - this->mark_failed(); - return; - } - this->y_raw_max_ = ((received[2])) | ((received[3] & 0xf0) << 4); + if (this->swap_x_y_) + std::swap(this->x_raw_max_, this->y_raw_max_); } this->set_power_state(true); } diff --git a/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp b/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp index 84811b818f..674ef51d64 100644 --- a/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp +++ b/esphome/components/gt911/touchscreen/gt911_touchscreen.cpp @@ -60,20 +60,25 @@ void GT911Touchscreen::setup() { } } } - if (err == i2c::ERROR_OK) { - err = this->write(GET_MAX_VALUES, 2); + if (this->x_raw_max_ == 0 || this->y_raw_max_ == 0) { + // no calibration? Attempt to read the max values from the touchscreen. if (err == i2c::ERROR_OK) { - err = this->read(data, sizeof(data)); + err = this->write(GET_MAX_VALUES, 2); if (err == i2c::ERROR_OK) { - if (this->x_raw_max_ == this->x_raw_min_) { + err = this->read(data, sizeof(data)); + if (err == i2c::ERROR_OK) { this->x_raw_max_ = encode_uint16(data[1], data[0]); - } - if (this->y_raw_max_ == this->y_raw_min_) { this->y_raw_max_ = encode_uint16(data[3], data[2]); + if (this->swap_x_y_) + std::swap(this->x_raw_max_, this->y_raw_max_); } - esph_log_d(TAG, "calibration max_x/max_y %d/%d", this->x_raw_max_, this->y_raw_max_); } } + if (err != i2c::ERROR_OK) { + ESP_LOGE(TAG, "Failed to read calibration values from touchscreen!"); + this->mark_failed(); + return; + } } if (err != i2c::ERROR_OK) { ESP_LOGE(TAG, "Failed to communicate!"); From 20c7778524510cc693c998cf6a2ab450a698426a Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 24 Mar 2025 20:35:42 +1100 Subject: [PATCH 2/7] [font] More robust handling of fixed font sizes. (#8443) Co-authored-by: Keith Burzinski --- esphome/components/font/__init__.py | 28 +- tests/components/font/Tamzen5x9b.bdf | 3246 ++++++++++++++++++++++++++ tests/components/font/common.yaml | 3 + 3 files changed, 3270 insertions(+), 7 deletions(-) create mode 100644 tests/components/font/Tamzen5x9b.bdf diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index 084574d09f..a405761c74 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -7,7 +7,15 @@ from pathlib import Path import re import esphome_glyphsets as glyphsets -from freetype import Face, ft_pixel_mode_grays, ft_pixel_mode_mono + +# pylint: disable=no-name-in-module +from freetype import ( + FT_LOAD_NO_BITMAP, + FT_LOAD_RENDER, + Face, + ft_pixel_mode_grays, + ft_pixel_mode_mono, +) import requests from esphome import external_files @@ -204,7 +212,7 @@ def validate_font_config(config): if font.get_char_index(x) != 0 ] - if font.has_fixed_sizes: + if not font.is_scalable: sizes = [pt_to_px(x.size) for x in font.available_sizes] if not sizes: raise cv.Invalid( @@ -507,10 +515,16 @@ async def to_code(config): # create the data array for all glyphs for codepoint in codepoints: font = point_font_map[codepoint] - format = font.get_format().decode("utf-8") - if format != "PCF": + if not font.is_scalable: + sizes = [pt_to_px(x.size) for x in font.available_sizes] + if size in sizes: + font.select_size(sizes.index(size)) + else: font.set_pixel_sizes(size, 0) - font.load_char(codepoint) + flags = FT_LOAD_RENDER + if bpp != 1: + flags |= FT_LOAD_NO_BITMAP + font.load_char(codepoint, flags) font.glyph.render(mode) width = font.glyph.bitmap.width height = font.glyph.bitmap.rows @@ -535,7 +549,7 @@ async def to_code(config): pos += 1 ascender = pt_to_px(font.size.ascender) if ascender == 0: - if font.has_fixed_sizes: + if not font.is_scalable: ascender = size else: _LOGGER.error( @@ -585,7 +599,7 @@ async def to_code(config): font_height = pt_to_px(base_font.size.height) ascender = pt_to_px(base_font.size.ascender) if font_height == 0: - if base_font.has_fixed_sizes: + if not base_font.is_scalable: font_height = size ascender = font_height else: diff --git a/tests/components/font/Tamzen5x9b.bdf b/tests/components/font/Tamzen5x9b.bdf new file mode 100644 index 0000000000..dcea6def61 --- /dev/null +++ b/tests/components/font/Tamzen5x9b.bdf @@ -0,0 +1,3246 @@ +STARTFONT 2.1 +FONT -Misc-Tamzen-Bold-R-Normal--9-65-100-100-C-50-ISO8859-1 +SIZE 9 100 100 +FONTBOUNDINGBOX 5 9 0 -2 +STARTPROPERTIES 24 +FONTNAME_REGISTRY "" +FOUNDRY "Misc" +FAMILY_NAME "Tamzen" +WEIGHT_NAME "Bold" +SLANT "R" +SETWIDTH_NAME "Normal" +ADD_STYLE_NAME "" +PIXEL_SIZE 9 +POINT_SIZE 65 +RESOLUTION_X 100 +RESOLUTION_Y 100 +SPACING "C" +AVERAGE_WIDTH 50 +CHARSET_REGISTRY "ISO10646" +CHARSET_ENCODING "1" +COPYRIGHT "(c) 2015 Scott Fial" +CAP_HEIGHT 5 +X_HEIGHT 4 +FONT_VERSION "1.11" +WEIGHT 10 +QUAD_WIDTH 5 +DEFAULT_CHAR 0 +FONT_DESCENT 2 +FONT_ASCENT 7 +ENDPROPERTIES +CHARS 189 + +STARTCHAR U+2592 +ENCODING 2 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +50 +A8 +50 +A8 +50 +A8 +50 +A8 +50 +ENDCHAR + +STARTCHAR U+00B0 +ENCODING 7 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +60 +D0 +60 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+2518 +ENCODING 11 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +20 +20 +20 +20 +E0 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+2510 +ENCODING 12 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +00 +E0 +20 +20 +20 +20 +ENDCHAR + +STARTCHAR U+250C +ENCODING 13 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +00 +38 +20 +20 +20 +20 +ENDCHAR + +STARTCHAR U+2514 +ENCODING 14 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +20 +20 +20 +20 +38 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+253C +ENCODING 15 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +20 +20 +20 +20 +F8 +20 +20 +20 +20 +ENDCHAR + +STARTCHAR U+2500 +ENCODING 18 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +00 +F8 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+251C +ENCODING 21 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +20 +20 +20 +20 +38 +20 +20 +20 +20 +ENDCHAR + +STARTCHAR U+2524 +ENCODING 22 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +20 +20 +20 +20 +E0 +20 +20 +20 +20 +ENDCHAR + +STARTCHAR U+2534 +ENCODING 23 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +20 +20 +20 +20 +F8 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+252C +ENCODING 24 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +00 +F8 +20 +20 +20 +20 +ENDCHAR + +STARTCHAR U+2502 +ENCODING 25 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +20 +20 +20 +20 +20 +20 +20 +20 +20 +ENDCHAR + +STARTCHAR U+00A3 +ENCODING 30 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +30 +60 +F0 +60 +60 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+0020 +ENCODING 32 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+0021 +ENCODING 33 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +60 +60 +60 +60 +00 +60 +00 +00 +ENDCHAR + +STARTCHAR U+0022 +ENCODING 34 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +F0 +F0 +A0 +00 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+0023 +ENCODING 35 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +50 +F0 +50 +F0 +F0 +50 +00 +00 +ENDCHAR + +STARTCHAR U+0024 +ENCODING 36 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +20 +20 +70 +60 +30 +F0 +40 +40 +ENDCHAR + +STARTCHAR U+0025 +ENCODING 37 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +80 +90 +30 +60 +C0 +90 +10 +00 +ENDCHAR + +STARTCHAR U+0026 +ENCODING 38 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +60 +D0 +60 +D8 +D0 +E8 +00 +00 +ENDCHAR + +STARTCHAR U+0027 +ENCODING 39 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +60 +60 +60 +00 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+0028 +ENCODING 40 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +30 +60 +C0 +C0 +C0 +60 +30 +00 +ENDCHAR + +STARTCHAR U+0029 +ENCODING 41 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +C0 +60 +30 +30 +30 +60 +C0 +00 +ENDCHAR + +STARTCHAR U+002A +ENCODING 42 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +20 +F0 +60 +E0 +A0 +00 +00 +00 +ENDCHAR + +STARTCHAR U+002B +ENCODING 43 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +60 +60 +F8 +60 +60 +00 +00 +ENDCHAR + +STARTCHAR U+002C +ENCODING 44 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +00 +00 +60 +60 +C0 +00 +ENDCHAR + +STARTCHAR U+002D +ENCODING 45 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +00 +F0 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+002E +ENCODING 46 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +00 +00 +60 +60 +00 +00 +ENDCHAR + +STARTCHAR U+002F +ENCODING 47 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +30 +30 +60 +60 +C0 +C0 +00 +ENDCHAR + +STARTCHAR U+0030 +ENCODING 48 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +60 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+0031 +ENCODING 49 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +60 +E0 +60 +60 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+0032 +ENCODING 50 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +E0 +30 +60 +C0 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+0033 +ENCODING 51 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +E0 +30 +60 +30 +E0 +00 +00 +ENDCHAR + +STARTCHAR U+0034 +ENCODING 52 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +30 +70 +B0 +F0 +30 +00 +00 +ENDCHAR + +STARTCHAR U+0035 +ENCODING 53 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +F0 +C0 +E0 +30 +E0 +00 +00 +ENDCHAR + +STARTCHAR U+0036 +ENCODING 54 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +60 +C0 +E0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+0037 +ENCODING 55 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +F0 +30 +60 +C0 +C0 +00 +00 +ENDCHAR + +STARTCHAR U+0038 +ENCODING 56 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +60 +D0 +60 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+0039 +ENCODING 57 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +60 +D0 +70 +30 +60 +00 +00 +ENDCHAR + +STARTCHAR U+003A +ENCODING 58 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +60 +60 +00 +60 +60 +00 +00 +ENDCHAR + +STARTCHAR U+003B +ENCODING 59 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +60 +60 +00 +60 +60 +C0 +00 +ENDCHAR + +STARTCHAR U+003C +ENCODING 60 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +30 +60 +C0 +60 +30 +00 +00 +ENDCHAR + +STARTCHAR U+003D +ENCODING 61 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +F0 +00 +F0 +00 +00 +00 +ENDCHAR + +STARTCHAR U+003E +ENCODING 62 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +C0 +60 +30 +60 +C0 +00 +00 +ENDCHAR + +STARTCHAR U+003F +ENCODING 63 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +60 +B0 +30 +60 +00 +60 +00 +00 +ENDCHAR + +STARTCHAR U+0040 +ENCODING 64 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +60 +D0 +D0 +D0 +C0 +C0 +70 +00 +ENDCHAR + +STARTCHAR U+0041 +ENCODING 65 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +20 +70 +B0 +F0 +B0 +00 +00 +ENDCHAR + +STARTCHAR U+0042 +ENCODING 66 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +E0 +D0 +E0 +D0 +E0 +00 +00 +ENDCHAR + +STARTCHAR U+0043 +ENCODING 67 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +70 +C0 +C0 +C0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+0044 +ENCODING 68 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +E0 +D0 +D0 +D0 +E0 +00 +00 +ENDCHAR + +STARTCHAR U+0045 +ENCODING 69 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +F0 +C0 +E0 +C0 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+0046 +ENCODING 70 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +F0 +C0 +E0 +C0 +C0 +00 +00 +ENDCHAR + +STARTCHAR U+0047 +ENCODING 71 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +70 +C0 +D0 +D0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+0048 +ENCODING 72 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +D0 +D0 +F0 +D0 +D0 +00 +00 +ENDCHAR + +STARTCHAR U+0049 +ENCODING 73 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +F0 +60 +60 +60 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+004A +ENCODING 74 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +30 +30 +30 +B0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+004B +ENCODING 75 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +D0 +D0 +E0 +D0 +D0 +00 +00 +ENDCHAR + +STARTCHAR U+004C +ENCODING 76 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +C0 +C0 +C0 +C0 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+004D +ENCODING 77 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +90 +F0 +F0 +90 +90 +00 +00 +ENDCHAR + +STARTCHAR U+004E +ENCODING 78 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +D0 +D0 +F0 +B0 +B0 +00 +00 +ENDCHAR + +STARTCHAR U+004F +ENCODING 79 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +60 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+0050 +ENCODING 80 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +E0 +D0 +E0 +C0 +C0 +00 +00 +ENDCHAR + +STARTCHAR U+0051 +ENCODING 81 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +60 +D0 +D0 +D0 +60 +30 +00 +ENDCHAR + +STARTCHAR U+0052 +ENCODING 82 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +E0 +D0 +E0 +E0 +D0 +00 +00 +ENDCHAR + +STARTCHAR U+0053 +ENCODING 83 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +70 +C0 +60 +30 +E0 +00 +00 +ENDCHAR + +STARTCHAR U+0054 +ENCODING 84 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +F0 +60 +60 +60 +60 +00 +00 +ENDCHAR + +STARTCHAR U+0055 +ENCODING 85 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +D0 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+0056 +ENCODING 86 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +D0 +D0 +D0 +E0 +40 +00 +00 +ENDCHAR + +STARTCHAR U+0057 +ENCODING 87 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +90 +90 +F0 +F0 +90 +00 +00 +ENDCHAR + +STARTCHAR U+0058 +ENCODING 88 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +D0 +60 +60 +60 +D0 +00 +00 +ENDCHAR + +STARTCHAR U+0059 +ENCODING 89 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +D0 +D0 +60 +60 +60 +00 +00 +ENDCHAR + +STARTCHAR U+005A +ENCODING 90 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +F0 +30 +60 +C0 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+005B +ENCODING 91 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +70 +60 +60 +60 +60 +60 +70 +00 +ENDCHAR + +STARTCHAR U+005C +ENCODING 92 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +C0 +C0 +60 +60 +30 +30 +00 +ENDCHAR + +STARTCHAR U+005D +ENCODING 93 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +E0 +60 +60 +60 +60 +60 +E0 +00 +ENDCHAR + +STARTCHAR U+005E +ENCODING 94 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +40 +E0 +A0 +00 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+005F +ENCODING 95 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +00 +00 +00 +00 +F8 +00 +ENDCHAR + +STARTCHAR U+0060 +ENCODING 96 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +80 +C0 +60 +20 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+0061 +ENCODING 97 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +70 +B0 +B0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+0062 +ENCODING 98 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +C0 +C0 +E0 +D0 +D0 +E0 +00 +00 +ENDCHAR + +STARTCHAR U+0063 +ENCODING 99 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +70 +C0 +C0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+0064 +ENCODING 100 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +30 +30 +70 +B0 +B0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+0065 +ENCODING 101 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +70 +B0 +E0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+0066 +ENCODING 102 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +30 +60 +F0 +60 +60 +60 +00 +00 +ENDCHAR + +STARTCHAR U+0067 +ENCODING 103 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +70 +D0 +D0 +70 +30 +60 +ENDCHAR + +STARTCHAR U+0068 +ENCODING 104 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +C0 +C0 +E0 +D0 +D0 +D0 +00 +00 +ENDCHAR + +STARTCHAR U+0069 +ENCODING 105 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +60 +00 +E0 +60 +60 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+006A +ENCODING 106 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +30 +00 +70 +30 +30 +30 +30 +E0 +ENDCHAR + +STARTCHAR U+006B +ENCODING 107 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +C0 +C0 +D0 +E0 +D0 +D0 +00 +00 +ENDCHAR + +STARTCHAR U+006C +ENCODING 108 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +E0 +60 +60 +60 +60 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+006D +ENCODING 109 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +D0 +F0 +D0 +D0 +00 +00 +ENDCHAR + +STARTCHAR U+006E +ENCODING 110 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +E0 +D0 +D0 +D0 +00 +00 +ENDCHAR + +STARTCHAR U+006F +ENCODING 111 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +60 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+0070 +ENCODING 112 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +E0 +D0 +D0 +E0 +C0 +C0 +ENDCHAR + +STARTCHAR U+0071 +ENCODING 113 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +70 +B0 +B0 +70 +30 +30 +ENDCHAR + +STARTCHAR U+0072 +ENCODING 114 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +F0 +C0 +C0 +C0 +00 +00 +ENDCHAR + +STARTCHAR U+0073 +ENCODING 115 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +70 +60 +30 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+0074 +ENCODING 116 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +60 +F0 +60 +60 +70 +00 +00 +ENDCHAR + +STARTCHAR U+0075 +ENCODING 117 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+0076 +ENCODING 118 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +D0 +D0 +E0 +40 +00 +00 +ENDCHAR + +STARTCHAR U+0077 +ENCODING 119 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +D0 +D0 +F0 +D0 +00 +00 +ENDCHAR + +STARTCHAR U+0078 +ENCODING 120 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +D0 +60 +60 +D0 +00 +00 +ENDCHAR + +STARTCHAR U+0079 +ENCODING 121 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +D0 +D0 +D0 +70 +30 +60 +ENDCHAR + +STARTCHAR U+007A +ENCODING 122 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +F0 +60 +C0 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+007B +ENCODING 123 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +38 +30 +30 +F0 +30 +30 +38 +00 +ENDCHAR + +STARTCHAR U+007C +ENCODING 124 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +60 +60 +60 +60 +60 +60 +60 +00 +ENDCHAR + +STARTCHAR U+007D +ENCODING 125 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +E0 +60 +60 +78 +60 +60 +E0 +00 +ENDCHAR + +STARTCHAR U+007E +ENCODING 126 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +50 +F0 +A0 +00 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+00A0 +ENCODING 160 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+00A1 +ENCODING 161 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +60 +00 +60 +60 +60 +60 +ENDCHAR + +STARTCHAR U+00A2 +ENCODING 162 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +20 +70 +C0 +C0 +70 +20 +00 +00 +ENDCHAR + +STARTCHAR U+00A3 +ENCODING 163 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +30 +60 +F0 +60 +60 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+00A4 +ENCODING 164 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +D0 +60 +D0 +D0 +60 +D0 +00 +00 +ENDCHAR + +STARTCHAR U+00A5 +ENCODING 165 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +D0 +60 +F0 +60 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00A6 +ENCODING 166 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +60 +60 +60 +00 +60 +60 +60 +00 +ENDCHAR + +STARTCHAR U+00A8 +ENCODING 168 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +A0 +00 +00 +00 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+00A9 +ENCODING 169 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +60 +90 +B0 +90 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00AB +ENCODING 171 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +00 +48 +D8 +48 +00 +00 +ENDCHAR + +STARTCHAR U+00AD +ENCODING 173 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +00 +F0 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+00B0 +ENCODING 176 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +60 +D0 +60 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+00B4 +ENCODING 180 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +10 +20 +00 +00 +00 +00 +00 +00 +ENDCHAR + +STARTCHAR U+00B8 +ENCODING 184 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +00 +00 +00 +00 +20 +60 +ENDCHAR + +STARTCHAR U+00BB +ENCODING 187 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +00 +90 +D8 +90 +00 +00 +ENDCHAR + +STARTCHAR U+00BF +ENCODING 191 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +60 +00 +60 +C0 +D0 +60 +ENDCHAR + +STARTCHAR U+00C0 +ENCODING 192 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +40 +20 +70 +B0 +F0 +B0 +00 +00 +ENDCHAR + +STARTCHAR U+00C1 +ENCODING 193 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +10 +20 +70 +B0 +F0 +B0 +00 +00 +ENDCHAR + +STARTCHAR U+00C2 +ENCODING 194 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +20 +50 +00 +70 +B0 +F0 +B0 +00 +00 +ENDCHAR + +STARTCHAR U+00C3 +ENCODING 195 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +D0 +B0 +00 +70 +B0 +F0 +B0 +00 +00 +ENDCHAR + +STARTCHAR U+00C4 +ENCODING 196 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +90 +00 +20 +70 +B0 +F0 +B0 +00 +00 +ENDCHAR + +STARTCHAR U+00C5 +ENCODING 197 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +60 +B0 +60 +B0 +F0 +B0 +00 +00 +ENDCHAR + +STARTCHAR U+00C6 +ENCODING 198 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +70 +A0 +F0 +A0 +B0 +00 +00 +ENDCHAR + +STARTCHAR U+00C7 +ENCODING 199 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +70 +C0 +C0 +C0 +70 +20 +60 +ENDCHAR + +STARTCHAR U+00C8 +ENCODING 200 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +80 +40 +F0 +C0 +E0 +C0 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+00C9 +ENCODING 201 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +10 +20 +F0 +C0 +E0 +C0 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+00CA +ENCODING 202 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +40 +A0 +F0 +C0 +E0 +C0 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+00CB +ENCODING 203 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +A0 +00 +F0 +C0 +E0 +C0 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+00CC +ENCODING 204 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +80 +40 +F0 +60 +60 +60 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+00CD +ENCODING 205 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +10 +20 +F0 +60 +60 +60 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+00CE +ENCODING 206 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +40 +A0 +F0 +60 +60 +60 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+00CF +ENCODING 207 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +A0 +00 +F0 +60 +60 +60 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+00D0 +ENCODING 208 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +E0 +50 +D0 +50 +E0 +00 +00 +ENDCHAR + +STARTCHAR U+00D1 +ENCODING 209 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +D0 +B0 +00 +D0 +F0 +B0 +B0 +00 +00 +ENDCHAR + +STARTCHAR U+00D2 +ENCODING 210 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +80 +40 +60 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00D3 +ENCODING 211 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +10 +20 +60 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00D4 +ENCODING 212 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +40 +A0 +60 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00D5 +ENCODING 213 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +D0 +B0 +00 +60 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00D6 +ENCODING 214 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +A0 +00 +60 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00D7 +ENCODING 215 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +D0 +60 +D0 +00 +00 +00 +ENDCHAR + +STARTCHAR U+00D8 +ENCODING 216 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +10 +60 +D0 +D0 +D0 +60 +80 +00 +ENDCHAR + +STARTCHAR U+00D9 +ENCODING 217 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +80 +40 +D0 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00DA +ENCODING 218 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +20 +40 +D0 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00DB +ENCODING 219 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +40 +A0 +D0 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00DC +ENCODING 220 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +A0 +00 +D0 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00DD +ENCODING 221 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +20 +40 +D0 +D0 +60 +60 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00DE +ENCODING 222 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +C0 +E0 +D0 +E0 +C0 +00 +00 +ENDCHAR + +STARTCHAR U+00DF +ENCODING 223 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +70 +D0 +E0 +D0 +E0 +00 +00 +ENDCHAR + +STARTCHAR U+00E0 +ENCODING 224 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +80 +40 +70 +B0 +B0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+00E1 +ENCODING 225 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +10 +20 +70 +B0 +B0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+00E2 +ENCODING 226 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +40 +A0 +00 +70 +B0 +B0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+00E3 +ENCODING 227 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +D0 +B0 +00 +70 +B0 +B0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+00E4 +ENCODING 228 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +A0 +00 +70 +B0 +B0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+00E5 +ENCODING 229 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +60 +B0 +60 +B0 +B0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+00E6 +ENCODING 230 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +F0 +70 +A0 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+00E7 +ENCODING 231 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +00 +70 +C0 +C0 +70 +20 +60 +ENDCHAR + +STARTCHAR U+00E8 +ENCODING 232 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +80 +40 +70 +B0 +E0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+00E9 +ENCODING 233 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +10 +20 +70 +B0 +E0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+00EA +ENCODING 234 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +40 +A0 +00 +70 +B0 +E0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+00EB +ENCODING 235 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +A0 +00 +70 +B0 +E0 +70 +00 +00 +ENDCHAR + +STARTCHAR U+00EC +ENCODING 236 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +80 +40 +E0 +60 +60 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+00ED +ENCODING 237 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +10 +20 +E0 +60 +60 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+00EE +ENCODING 238 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +40 +A0 +00 +E0 +60 +60 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+00EF +ENCODING 239 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +A0 +00 +E0 +60 +60 +F0 +00 +00 +ENDCHAR + +STARTCHAR U+00F0 +ENCODING 240 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +40 +F0 +20 +60 +B0 +B0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00F1 +ENCODING 241 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +D0 +B0 +00 +E0 +D0 +D0 +D0 +00 +00 +ENDCHAR + +STARTCHAR U+00F2 +ENCODING 242 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +80 +40 +60 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00F3 +ENCODING 243 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +10 +20 +60 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00F4 +ENCODING 244 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +40 +A0 +00 +60 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00F5 +ENCODING 245 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +D0 +B0 +00 +60 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00F6 +ENCODING 246 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +A0 +00 +60 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00F7 +ENCODING 247 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +60 +00 +F0 +00 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00F8 +ENCODING 248 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +00 +10 +60 +D0 +D0 +60 +80 +00 +ENDCHAR + +STARTCHAR U+00F9 +ENCODING 249 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +80 +40 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00FA +ENCODING 250 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +20 +40 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00FB +ENCODING 251 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +40 +A0 +00 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00FC +ENCODING 252 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +A0 +00 +D0 +D0 +D0 +60 +00 +00 +ENDCHAR + +STARTCHAR U+00FD +ENCODING 253 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +20 +40 +D0 +D0 +D0 +70 +30 +60 +ENDCHAR + +STARTCHAR U+00FE +ENCODING 254 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +C0 +C0 +E0 +D0 +D0 +E0 +C0 +C0 +ENDCHAR + +STARTCHAR U+00FF +ENCODING 255 +SWIDTH 392 0 +DWIDTH 5 0 +BBX 5 9 0 -2 +BITMAP +00 +A0 +00 +D0 +D0 +D0 +70 +30 +60 +ENDCHAR + +ENDFONT diff --git a/tests/components/font/common.yaml b/tests/components/font/common.yaml index 5be9faf5be..fb50fc3336 100644 --- a/tests/components/font/common.yaml +++ b/tests/components/font/common.yaml @@ -43,6 +43,9 @@ font: id: default_font - file: $component_dir/x11.pcf id: pcf_font + - file: $component_dir/Tamzen5x9b.bdf + id: bdf_font + size: 7 i2c: scl: ${i2c_scl} From f131186e6bd4dcc9bddbab1cb7b74f7fc9ea7156 Mon Sep 17 00:00:00 2001 From: Samuel Sieb Date: Tue, 25 Mar 2025 01:33:53 -0700 Subject: [PATCH 3/7] fix 1bpp rendering (#8463) --- esphome/components/font/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/esphome/components/font/__init__.py b/esphome/components/font/__init__.py index a405761c74..be88fdb957 100644 --- a/esphome/components/font/__init__.py +++ b/esphome/components/font/__init__.py @@ -12,8 +12,8 @@ import esphome_glyphsets as glyphsets from freetype import ( FT_LOAD_NO_BITMAP, FT_LOAD_RENDER, + FT_LOAD_TARGET_MONO, Face, - ft_pixel_mode_grays, ft_pixel_mode_mono, ) import requests @@ -509,7 +509,6 @@ async def to_code(config): glyph_args = {} data = [] bpp = config[CONF_BPP] - mode = ft_pixel_mode_grays scale = 256 // (1 << bpp) size = config[CONF_SIZE] # create the data array for all glyphs @@ -524,8 +523,9 @@ async def to_code(config): flags = FT_LOAD_RENDER if bpp != 1: flags |= FT_LOAD_NO_BITMAP + else: + flags |= FT_LOAD_TARGET_MONO font.load_char(codepoint, flags) - font.glyph.render(mode) width = font.glyph.bitmap.width height = font.glyph.bitmap.rows buffer = font.glyph.bitmap.buffer From 8fcbd57f2f9730d5664b6c6bc0e9145498112829 Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 25 Mar 2025 11:16:12 -0500 Subject: [PATCH 4/7] [media_player] Don't reset enqueue command (#8465) --- esphome/components/media_player/media_player.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/esphome/components/media_player/media_player.cpp b/esphome/components/media_player/media_player.cpp index 01304d9135..32da7ee265 100644 --- a/esphome/components/media_player/media_player.cpp +++ b/esphome/components/media_player/media_player.cpp @@ -56,7 +56,8 @@ const char *media_player_command_to_string(MediaPlayerCommand command) { void MediaPlayerCall::validate_() { if (this->media_url_.has_value()) { - if (this->command_.has_value()) { + if (this->command_.has_value() && this->command_.value() != MEDIA_PLAYER_COMMAND_ENQUEUE) { + // Don't remove an enqueue command ESP_LOGW(TAG, "MediaPlayerCall: Setting both command and media_url is not needed."); this->command_.reset(); } From ea4b573f9a3e38582656797d87c04e7332789a5f Mon Sep 17 00:00:00 2001 From: Kevin Ahrendt Date: Tue, 25 Mar 2025 15:20:56 -0500 Subject: [PATCH 5/7] [speaker] Bugfix: Fix rapidly adding items to playlist (#8466) Co-authored-by: Keith Burzinski --- .../media_player/speaker_media_player.cpp | 83 +++++-------------- .../media_player/speaker_media_player.h | 8 +- 2 files changed, 25 insertions(+), 66 deletions(-) diff --git a/esphome/components/speaker/media_player/speaker_media_player.cpp b/esphome/components/speaker/media_player/speaker_media_player.cpp index 0a2585ce60..80ddfb2f04 100644 --- a/esphome/components/speaker/media_player/speaker_media_player.cpp +++ b/esphome/components/speaker/media_player/speaker_media_player.cpp @@ -138,77 +138,48 @@ void SpeakerMediaPlayer::watch_media_commands_() { } MediaCallCommand media_command; - esp_err_t err = ESP_OK; if (xQueueReceive(this->media_control_command_queue_, &media_command, 0) == pdTRUE) { - bool new_url = media_command.new_url.has_value() && media_command.new_url.value(); - bool new_file = media_command.new_file.has_value() && media_command.new_file.value(); + bool enqueue = media_command.enqueue.has_value() && media_command.enqueue.value(); - if (new_url || new_file) { - bool enqueue = media_command.enqueue.has_value() && media_command.enqueue.value(); + if (media_command.url.has_value() || media_command.file.has_value()) { + PlaylistItem playlist_item; + if (media_command.url.has_value()) { + playlist_item.url = *media_command.url.value(); + delete media_command.url.value(); + } + if (media_command.file.has_value()) { + playlist_item.file = media_command.file.value(); + } if (this->single_pipeline_() || (media_command.announce.has_value() && media_command.announce.value())) { - // Announcement playlist/pipeline - if (!enqueue) { - // Clear the queue and ensure the loaded next item doesn't start playing + // Ensure the loaded next item doesn't start playing, clear the queue, start the file, and unpause this->cancel_timeout("next_ann"); this->announcement_playlist_.clear(); - } - - PlaylistItem playlist_item; - if (new_url) { - playlist_item.url = this->announcement_url_; - if (!enqueue) { - // Not adding to the queue, so directly start playback and internally unpause the pipeline - this->announcement_pipeline_->start_url(playlist_item.url.value()); - this->announcement_pipeline_->set_pause_state(false); - } - } else { - playlist_item.file = this->announcement_file_; - if (!enqueue) { - // Not adding to the queue, so directly start playback and internally unpause the pipeline + if (media_command.file.has_value()) { this->announcement_pipeline_->start_file(playlist_item.file.value()); - this->announcement_pipeline_->set_pause_state(false); + } else if (media_command.url.has_value()) { + this->announcement_pipeline_->start_url(playlist_item.url.value()); } + this->announcement_pipeline_->set_pause_state(false); } this->announcement_playlist_.push_back(playlist_item); } else { - // Media playlist/pipeline - if (!enqueue) { - // Clear the queue and ensure the loaded next item doesn't start playing + // Ensure the loaded next item doesn't start playing, clear the queue, start the file, and unpause this->cancel_timeout("next_media"); this->media_playlist_.clear(); - } - - this->is_paused_ = false; - PlaylistItem playlist_item; - if (new_url) { - playlist_item.url = this->media_url_; - if (!enqueue) { - // Not adding to the queue, so directly start playback and internally unpause the pipeline - this->media_pipeline_->start_url(playlist_item.url.value()); - this->media_pipeline_->set_pause_state(false); - } - } else { - playlist_item.file = this->media_file_; - if (!enqueue) { - // Not adding to the queue, so directly start playback and internally unpause the pipeline + if (media_command.file.has_value()) { this->media_pipeline_->start_file(playlist_item.file.value()); - this->media_pipeline_->set_pause_state(false); + } else if (media_command.url.has_value()) { + this->media_pipeline_->start_url(playlist_item.url.value()); } + this->media_pipeline_->set_pause_state(false); } this->media_playlist_.push_back(playlist_item); } - if (err != ESP_OK) { - ESP_LOGE(TAG, "Error starting the audio pipeline: %s", esp_err_to_name(err)); - this->status_set_error(); - } else { - this->status_clear_error(); - } - return; // Don't process the new file play command further } @@ -429,12 +400,10 @@ void SpeakerMediaPlayer::play_file(audio::AudioFile *media_file, bool announceme MediaCallCommand media_command; - media_command.new_file = true; + media_command.file = media_file; if (this->single_pipeline_() || announcement) { - this->announcement_file_ = media_file; media_command.announce = true; } else { - this->media_file_ = media_file; media_command.announce = false; } media_command.enqueue = enqueue; @@ -456,14 +425,8 @@ void SpeakerMediaPlayer::control(const media_player::MediaPlayerCall &call) { } if (call.get_media_url().has_value()) { - std::string new_uri = call.get_media_url().value(); - - media_command.new_url = true; - if (this->single_pipeline_() || (call.get_announcement().has_value() && call.get_announcement().value())) { - this->announcement_url_ = new_uri; - } else { - this->media_url_ = new_uri; - } + media_command.url = new std::string( + call.get_media_url().value()); // Must be manually deleted after receiving media_command from a queue if (call.get_command().has_value()) { if (call.get_command().value() == media_player::MEDIA_PLAYER_COMMAND_ENQUEUE) { diff --git a/esphome/components/speaker/media_player/speaker_media_player.h b/esphome/components/speaker/media_player/speaker_media_player.h index 6cbce91866..81eb72a830 100644 --- a/esphome/components/speaker/media_player/speaker_media_player.h +++ b/esphome/components/speaker/media_player/speaker_media_player.h @@ -24,8 +24,8 @@ struct MediaCallCommand { optional command; optional volume; optional announce; - optional new_url; - optional new_file; + optional url; // Must be manually deleted after receiving this struct from a queue + optional file; optional enqueue; }; @@ -109,15 +109,11 @@ class SpeakerMediaPlayer : public Component, public media_player::MediaPlayer { optional media_format_; AudioPipelineState media_pipeline_state_{AudioPipelineState::STOPPED}; - std::string media_url_{}; // only modified by control function - audio::AudioFile *media_file_{}; // only modified by play_file function bool media_repeat_one_{false}; uint32_t media_playlist_delay_ms_{0}; optional announcement_format_; AudioPipelineState announcement_pipeline_state_{AudioPipelineState::STOPPED}; - std::string announcement_url_{}; // only modified by control function - audio::AudioFile *announcement_file_{}; // only modified by play_file function bool announcement_repeat_one_{false}; uint32_t announcement_playlist_delay_ms_{0}; From f95b2ba898d4943c7b693d55450efb79ab509943 Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 25 Mar 2025 15:21:10 -0500 Subject: [PATCH 6/7] [ld2450] Fix bluetooth state not reported correctly (#8458) --- esphome/components/ld2450/ld2450.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/esphome/components/ld2450/ld2450.cpp b/esphome/components/ld2450/ld2450.cpp index 5bd7635dec..3db065ba1a 100644 --- a/esphome/components/ld2450/ld2450.cpp +++ b/esphome/components/ld2450/ld2450.cpp @@ -15,6 +15,7 @@ namespace esphome { namespace ld2450 { static const char *const TAG = "ld2450"; +static const char *const NO_MAC("08:05:04:03:02:01"); static const char *const UNKNOWN_MAC("unknown"); // LD2450 UART Serial Commands @@ -614,12 +615,12 @@ bool LD2450Component::handle_ack_data_(uint8_t *buffer, uint8_t len) { ESP_LOGV(TAG, "MAC address: %s", this->mac_.c_str()); #ifdef USE_TEXT_SENSOR if (this->mac_text_sensor_ != nullptr) { - this->mac_text_sensor_->publish_state(this->mac_); + this->mac_text_sensor_->publish_state(this->mac_ == NO_MAC ? UNKNOWN_MAC : this->mac_); } #endif #ifdef USE_SWITCH if (this->bluetooth_switch_ != nullptr) { - this->bluetooth_switch_->publish_state(this->mac_ != UNKNOWN_MAC); + this->bluetooth_switch_->publish_state(this->mac_ != NO_MAC); } #endif break; From 031b1c8bd023d555e44346f2ebe03c0019f006ab Mon Sep 17 00:00:00 2001 From: Keith Burzinski Date: Tue, 25 Mar 2025 15:22:11 -0500 Subject: [PATCH 7/7] Bump version to 2025.3.2 --- esphome/const.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/const.py b/esphome/const.py index 6adc8ef5be..2851578029 100644 --- a/esphome/const.py +++ b/esphome/const.py @@ -1,6 +1,6 @@ """Constants used by esphome.""" -__version__ = "2025.3.1" +__version__ = "2025.3.2" ALLOWED_NAME_CHARS = "abcdefghijklmnopqrstuvwxyz0123456789-_" VALID_SUBSTITUTIONS_CHARACTERS = (