From 117956acb9f0f4f278f9fcea02670d94aec4653b Mon Sep 17 00:00:00 2001 From: Yuki Date: Wed, 5 Nov 2025 18:15:55 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E9=9D=9E=E6=95=B4=E6=95=B0=E7=BC=A9?= =?UTF-8?q?=E6=94=BE=E6=AF=94=E7=9A=84=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Graphics/Bitmap_fonts/glyph_shrink.cpp | 4 ++-- src/Graphics/Renderer/renderer.cpp | 4 ++-- src/Graphics/Renderer/renderer.hpp | 4 ++-- src/Plugins/Qt/qt_gui.cpp | 6 +++--- src/Scheme/Glue/build-glue-basic.scm | 4 ++-- src/Scheme/Glue/glue_basic.lua | 4 ++-- 6 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/Graphics/Bitmap_fonts/glyph_shrink.cpp b/src/Graphics/Bitmap_fonts/glyph_shrink.cpp index 46ef7b7bf..f4709dcd3 100644 --- a/src/Graphics/Bitmap_fonts/glyph_shrink.cpp +++ b/src/Graphics/Bitmap_fonts/glyph_shrink.cpp @@ -251,8 +251,8 @@ shrink (glyph gl, int xfactor, int yfactor, SI& xo, SI& yo) { return glyph (0, 0, 0, 0, new_depth); } - int tx= ((xfactor / 3) * (retina_factor + 1)) / 2; - int ty= ((yfactor / 3) * (retina_factor + 1)) / 2; + int tx= ((xfactor / 3) * (int(retina_factor) + 1)) / 2; + int ty= ((yfactor / 3) * (int(retina_factor) + 1)) / 2; int dx= 0, dy= 0; if ((gl->status == 0) && (xfactor > 1)) dx= get_hor_shift (gl, xfactor, tx); // if ((gl->status==0) && (yfactor>1)) dy= get_ver_shift (gl, yfactor, ty); diff --git a/src/Graphics/Renderer/renderer.cpp b/src/Graphics/Renderer/renderer.cpp index 54aeca3be..2d0ced74c 100644 --- a/src/Graphics/Renderer/renderer.cpp +++ b/src/Graphics/Renderer/renderer.cpp @@ -30,7 +30,7 @@ int retina_factor= 2; bool retina_manual= false; int retina_zoom = 1; double retina_scale = 1.0; -int retina_factor= 1; +double retina_factor= 1.0; #endif int retina_icons= 1; @@ -53,7 +53,7 @@ get_retina_scale () { return retina_scale; } void -set_retina_factor (int f) { +set_retina_factor (double f) { retina_factor= f; } void diff --git a/src/Graphics/Renderer/renderer.hpp b/src/Graphics/Renderer/renderer.hpp index 8e1afd8b1..4dd734d9c 100644 --- a/src/Graphics/Renderer/renderer.hpp +++ b/src/Graphics/Renderer/renderer.hpp @@ -160,7 +160,7 @@ void reverse (int& r, int& g, int& b); extern bool retina_manual; extern bool retina_iman; -extern int retina_factor; +extern double retina_factor; extern int retina_zoom; extern int retina_icons; extern double retina_scale; @@ -168,7 +168,7 @@ int get_retina_factor (); // MacOS style int get_retina_zoom (); // GNU/Linux and Windows style int get_retina_icons (); double get_retina_scale (); -void set_retina_factor (int f); +void set_retina_factor (double f); void set_retina_zoom (int z); void set_retina_icons (int i); void set_retina_scale (double s); diff --git a/src/Plugins/Qt/qt_gui.cpp b/src/Plugins/Qt/qt_gui.cpp index 2811f95d5..dd5938df9 100644 --- a/src/Plugins/Qt/qt_gui.cpp +++ b/src/Plugins/Qt/qt_gui.cpp @@ -171,7 +171,7 @@ qt_gui_rep::qt_gui_rep (int& argc, char** argv) if (mac_hidpi == 2) { if (DEBUG_STD) debug_boot << "Setting up HiDPI mode\n"; #if (QT_VERSION < 0x050000) - retina_factor= 2; + retina_factor= 2.0; if (tm_style_sheet == "") retina_scale= 1.4; else retina_scale= 1.0; if (!retina_iman) { @@ -181,7 +181,7 @@ qt_gui_rep::qt_gui_rep (int& argc, char** argv) // retina_icons = 2; // FIXME: why is this not better? } #else - retina_factor= 2; + retina_factor= 2.0; #endif } #else @@ -201,7 +201,7 @@ qt_gui_rep::qt_gui_rep (int& argc, char** argv) #endif } if (has_user_preference ("retina-factor")) - retina_factor= get_user_preference ("retina-factor") == "on" ? 2 : 1; + retina_factor= get_user_preference ("retina-factor") == "on" ? 2.0 : 1.0; if (has_user_preference ("retina-zoom")) retina_zoom= get_user_preference ("retina-zoom") == "on" ? 2 : 1; if (has_user_preference ("retina-icons")) diff --git a/src/Scheme/Glue/build-glue-basic.scm b/src/Scheme/Glue/build-glue-basic.scm index fbd830cff..0e5b07cbf 100644 --- a/src/Scheme/Glue/build-glue-basic.scm +++ b/src/Scheme/Glue/build-glue-basic.scm @@ -37,11 +37,11 @@ (default-chinese-font default_chinese_font_name (string)) (default-japanese-font default_japanese_font_name (string)) (default-korean-font default_korean_font_name (string)) - (get-retina-factor get_retina_factor (int)) + (get-retina-factor get_retina_factor (double)) (get-retina-zoom get_retina_zoom (int)) (get-retina-icons get_retina_icons (int)) (get-retina-scale get_retina_scale (double)) - (set-retina-factor set_retina_factor (void int)) + (set-retina-factor set_retina_factor (void double)) (set-retina-zoom set_retina_zoom (void int)) (set-retina-icons set_retina_icons (void int)) (set-retina-scale set_retina_scale (void double)) diff --git a/src/Scheme/Glue/glue_basic.lua b/src/Scheme/Glue/glue_basic.lua index 1eaa399cf..3fc0ef2a6 100644 --- a/src/Scheme/Glue/glue_basic.lua +++ b/src/Scheme/Glue/glue_basic.lua @@ -44,7 +44,7 @@ function main() { scm_name = "get-retina-factor", cpp_name = "get_retina_factor", - ret_type = "int" + ret_type = "double" }, { scm_name = "get-retina-zoom", @@ -66,7 +66,7 @@ function main() cpp_name = "set_retina_factor", ret_type = "void", arg_list = { - "int" + "double" } }, { -- Gitee From ad702719bba9ae6b645031f03b445992d87e1aad Mon Sep 17 00:00:00 2001 From: Yuki Date: Wed, 5 Nov 2025 18:16:08 +0800 Subject: [PATCH 2/5] wip --- src/Graphics/Bitmap_fonts/glyph_shrink.cpp | 4 ++-- src/Graphics/Renderer/renderer.cpp | 4 ++-- src/Graphics/Renderer/renderer.hpp | 2 +- src/Plugins/Qt/QTMApplication.hpp | 4 ++-- src/System/Boot/init_texmacs.cpp | 14 +++++++------- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Graphics/Bitmap_fonts/glyph_shrink.cpp b/src/Graphics/Bitmap_fonts/glyph_shrink.cpp index f4709dcd3..1dec47d79 100644 --- a/src/Graphics/Bitmap_fonts/glyph_shrink.cpp +++ b/src/Graphics/Bitmap_fonts/glyph_shrink.cpp @@ -251,8 +251,8 @@ shrink (glyph gl, int xfactor, int yfactor, SI& xo, SI& yo) { return glyph (0, 0, 0, 0, new_depth); } - int tx= ((xfactor / 3) * (int(retina_factor) + 1)) / 2; - int ty= ((yfactor / 3) * (int(retina_factor) + 1)) / 2; + int tx= ((xfactor / 3) * (int(retina_factor + 0.5) + 1)) / 2; + int ty= ((yfactor / 3) * (int(retina_factor + 0.5) + 1)) / 2; int dx= 0, dy= 0; if ((gl->status == 0) && (xfactor > 1)) dx= get_hor_shift (gl, xfactor, tx); // if ((gl->status==0) && (yfactor>1)) dy= get_ver_shift (gl, yfactor, ty); diff --git a/src/Graphics/Renderer/renderer.cpp b/src/Graphics/Renderer/renderer.cpp index 2d0ced74c..96079ff5a 100644 --- a/src/Graphics/Renderer/renderer.cpp +++ b/src/Graphics/Renderer/renderer.cpp @@ -25,7 +25,7 @@ int std_shrinkf= 5; bool retina_manual= true; int retina_zoom = 1; double retina_scale = 1.0; -int retina_factor= 2; +double retina_factor= 2.0; #else bool retina_manual= false; int retina_zoom = 1; @@ -36,7 +36,7 @@ double retina_factor= 1.0; int retina_icons= 1; bool retina_iman = false; -int +double get_retina_factor () { return retina_factor; } diff --git a/src/Graphics/Renderer/renderer.hpp b/src/Graphics/Renderer/renderer.hpp index 4dd734d9c..7d38f18cb 100644 --- a/src/Graphics/Renderer/renderer.hpp +++ b/src/Graphics/Renderer/renderer.hpp @@ -164,7 +164,7 @@ extern double retina_factor; extern int retina_zoom; extern int retina_icons; extern double retina_scale; -int get_retina_factor (); // MacOS style +double get_retina_factor (); // MacOS style int get_retina_zoom (); // GNU/Linux and Windows style int get_retina_icons (); double get_retina_scale (); diff --git a/src/Plugins/Qt/QTMApplication.hpp b/src/Plugins/Qt/QTMApplication.hpp index 60ad7f8f6..25646f104 100644 --- a/src/Plugins/Qt/QTMApplication.hpp +++ b/src/Plugins/Qt/QTMApplication.hpp @@ -126,12 +126,12 @@ public: #if (QT_VERSION < 0x060000) if (!retina_manual) { qreal ratio = QGuiApplication::primaryScreen ()->devicePixelRatio (); - retina_factor= qRound (ratio - 0.1); + retina_factor= ratio; } #else if (!retina_manual) { qreal ratio = QApplication::primaryScreen ()->devicePixelRatio (); - retina_factor= qRound (ratio - 0.1); + retina_factor= ratio; } #endif } diff --git a/src/System/Boot/init_texmacs.cpp b/src/System/Boot/init_texmacs.cpp index 587d790a1..9fe474d4a 100644 --- a/src/System/Boot/init_texmacs.cpp +++ b/src/System/Boot/init_texmacs.cpp @@ -648,7 +648,7 @@ TeXmacs_main (int argc, char** argv) { else if ((s == "-r") || (s == "-reverse")) set_reverse_colors (true); else if (s == "-no-retina") { retina_manual= true; - retina_factor= 1; + retina_factor= 1.0; retina_zoom = 1; retina_icons = 1; retina_scale = 1.0; @@ -656,15 +656,15 @@ TeXmacs_main (int argc, char** argv) { else if ((s == "-R") || (s == "-retina")) { retina_manual= true; #ifdef MACOSX_EXTENSIONS - retina_factor= 2; + retina_factor= 2.0; retina_zoom = 1; retina_scale = 1.4; #elif defined(OS_WASM) - retina_factor= 2; + retina_factor= 2.0; retina_zoom = 2; retina_scale = (tm_style_sheet == "" ? 1.0 : 1.6666); #else - retina_factor= 1; + retina_factor= 1.0; retina_zoom = 2; retina_scale = (tm_style_sheet == "" ? 1.0 : 1.6666); #endif @@ -766,18 +766,18 @@ TeXmacs_main (int argc, char** argv) { // Further options via environment variables if (get_env ("TEXMACS_RETINA") == "off") { retina_manual= true; - retina_factor= 1; + retina_factor= 1.0; retina_icons = 1; retina_scale = 1.0; } if (get_env ("TEXMACS_RETINA") == "on") { retina_manual= true; #ifdef MACOSX_EXTENSIONS - retina_factor= 2; + retina_factor= 2.0; retina_zoom = 1; retina_scale = 1.4; #else - retina_factor= 1; + retina_factor= 1.0; retina_zoom = 2; retina_scale = (tm_style_sheet == "" ? 1.0 : 1.6666); #endif -- Gitee From 4196738b93a09c947277c9bd9366239e9576f1f4 Mon Sep 17 00:00:00 2001 From: Yuki Date: Wed, 5 Nov 2025 19:21:55 +0800 Subject: [PATCH 3/5] wip --- devel/202_52.md | 74 +++++++++++++++++++- src/Graphics/Renderer/renderer.cpp | 20 +++--- src/Plugins/MuPDF/mupdf_qt_simple_widget.cpp | 15 ++-- src/Plugins/Qt/QTMWidget.cpp | 39 ++++++----- src/Plugins/Qt/qt_simple_widget.cpp | 31 ++++---- 5 files changed, 131 insertions(+), 48 deletions(-) diff --git a/devel/202_52.md b/devel/202_52.md index ca876c669..388b5f1cd 100644 --- a/devel/202_52.md +++ b/devel/202_52.md @@ -2,11 +2,13 @@ 本文档记录了修复 Windows 上高 DPI所做的修改。 -偏移问题 [x] -实现对 125%/150% 的彻底支持 [ ] +- [x] 偏移问题 +- [x] 实现对 125%/150% 的彻底支持 ## 如何测试 +在Linux设备上,缩放比设置125%/150%,看编辑区域输入文字是否会模糊 + 在Windows设备上,缩放比设置125%/150%,然后主要测试三个地方: 在main分支上 @@ -15,6 +17,74 @@ - 点击 `编辑 -> 首选项` 把弹窗移动到屏幕右侧,点击选择框会出现偏移 - 点击 `格式 -> 页面` ,点击辅助窗口上的选择框,会偏移 +## 2025/11/5 + +### What + +使Linux支持非整百缩放比 + +### How + +#### 具体实施步骤 + +第一步:修改基础类型定义 + +``` + // renderer.hpp:163 + extern double retina_factor; // 从 int 改为 double + + // renderer.cpp:33 + double retina_factor = 1.0; // 从 int 改为 double +``` + +第二步:更新相关函数签名 + +``` + // renderer.hpp:171 + void set_retina_factor(double f); // 从 int 改为 double + + // renderer.cpp:56 + void set_retina_factor(double f) { // 从 int 改为 double + retina_factor = f; + } +``` + +第三步:更新Scheme绑定 + +``` + // build-glue-basic.scm:40,44 + (get-retina-factor get_retina_factor (double)) // 从 int 改为 double + (set-retina-factor set_retina_factor (void double)) // 从 int 改为 double + + // glue_basic.lua:46,66 + cpp_name = "get_retina_factor", // 返回类型改为 double + cpp_name = "set_retina_factor", // 参数类型改为 double +``` + +第四步:更新所有使用位置 + +需要系统性地检查所有使用 retina_factor 的地方,确保: + +1. 乘法运算:保持浮点运算精度 +2. 除法运算:正确处理浮点除法 +3. 坐标转换:使用浮点坐标而非整数坐标 +4. 尺寸计算:使用浮点尺寸而非整数尺寸 + +第五步:更新Qt集成代码 + +在 QTMApplication.hpp 中,将当前的整数舍入逻辑改为直接使用浮点值: + +``` + // 当前代码(需要修改) + retina_factor = qRound(ratio - 0.1); // 改为直接使用浮点值 +``` + +然后解决了以下细节问题 + +- 选中框被截断 +- 缩放会有线条 +- 伸缩弹窗宽度,会有重影 + ## 2025/09/29 ### What diff --git a/src/Graphics/Renderer/renderer.cpp b/src/Graphics/Renderer/renderer.cpp index 96079ff5a..ef981f969 100644 --- a/src/Graphics/Renderer/renderer.cpp +++ b/src/Graphics/Renderer/renderer.cpp @@ -283,24 +283,24 @@ renderer_rep::is_visible (SI x1, SI y1, SI x2, SI y2) { void renderer_rep::encode (SI& x, SI& y) { - x= (x * pixel) - ox; - y= ((-y) * pixel) - oy; + x= (SI) tm_round ((double) x * pixel) - ox; + y= (SI) tm_round ((double) (-y) * pixel) - oy; } void renderer_rep::decode (SI& x, SI& y) { x+= ox; y+= oy; - if (x >= 0) x= x / pixel; - else x= (x - pixel + 1) / pixel; - if (y >= 0) y= -(y / pixel); - else y= -((y - pixel + 1) / pixel); + if (x >= 0) x= (SI) tm_round ((double) x / pixel); + else x= (SI) tm_round ((double) (x - pixel + 1) / pixel); + if (y >= 0) y= -(SI) tm_round ((double) y / pixel); + else y= -(SI) tm_round ((double) (y - pixel + 1) / pixel); } void renderer_rep::encode (double x, double y, SI& rx, SI& ry) { - rx= ((SI) ((x + 0.5) * pixel)) - ox; - ry= ((SI) (((-y) + 0.5) * pixel)) - oy; + rx= (SI) tm_round ((x + 0.5) * pixel) - ox; + ry= (SI) tm_round (((-y) + 0.5) * pixel) - oy; } void @@ -310,8 +310,8 @@ renderer_rep::decode (SI x, SI y, double& rx, double& ry) { } #define RND(x) \ - (((x) >= 0) ? (((x) / retina_pixel) * retina_pixel) \ - : ((((x) - retina_pixel + 1) / retina_pixel) * retina_pixel)) + (((x) >= 0) ? ((SI) tm_round ((double) (x) / retina_pixel) * retina_pixel) \ + : ((SI) tm_round ((double) ((x) - retina_pixel + 1) / retina_pixel) * retina_pixel)) void renderer_rep::round (SI& x, SI& y) { diff --git a/src/Plugins/MuPDF/mupdf_qt_simple_widget.cpp b/src/Plugins/MuPDF/mupdf_qt_simple_widget.cpp index 49d26e7c6..5c2baddee 100644 --- a/src/Plugins/MuPDF/mupdf_qt_simple_widget.cpp +++ b/src/Plugins/MuPDF/mupdf_qt_simple_widget.cpp @@ -21,7 +21,8 @@ qt_simple_widget_rep::repaint_invalid_regions () { coord2 pt_or = from_qpoint (backing_pos); coord2 pt_new_or= from_qpoint (origin); - QSize _newSize= retina_factor * canvas ()->surface ()->size (); + QSize _newSize (qCeil (retina_factor * canvas ()->surface ()->size ().width ()), + qCeil (retina_factor * canvas ()->surface ()->size ().height ())); bs_ox= -pt_or.x1 * retina_factor; bs_oy= -pt_or.x2 * retina_factor; @@ -86,7 +87,7 @@ qt_simple_widget_rep::repaint_invalid_regions () { // syncronize all the picture, just to be safe qrgn+= QRect (QPoint (0, 0), - QSize (new_bs_w / retina_factor, new_bs_h / retina_factor)); + QSize (qRound (new_bs_w / retina_factor), qRound (new_bs_h / retina_factor))); // update the state bs_ox = new_bs_ox; @@ -116,9 +117,13 @@ qt_simple_widget_rep::repaint_invalid_regions () { while (!is_nil (rects)) { rectangle r = copy (rects->item); rectangle r0= rects->item; - QRect qr= QRect (r0->x1 / retina_factor, r0->y1 / retina_factor, - (r0->x2 - r0->x1) / retina_factor, - (r0->y2 - r0->y1) / retina_factor); + // Ensure pixel-perfect alignment by rounding coordinates consistently + // Use ceil for x2/y2 to ensure we cover the entire area and avoid gaps + int x1_px = qFloor (r0->x1 / retina_factor); + int y1_px = qFloor (r0->y1 / retina_factor); + int x2_px = qCeil (r0->x2 / retina_factor); + int y2_px = qCeil (r0->y2 / retina_factor); + QRect qr= QRect (x1_px, y1_px, x2_px - x1_px, y2_px - y1_px); // cout << "repainting " << r0 << "\n"; ren->set_origin (ox, oy); ren->encode (r->x1, r->y1); diff --git a/src/Plugins/Qt/QTMWidget.cpp b/src/Plugins/Qt/QTMWidget.cpp index 017c0ee7c..624b6abdb 100644 --- a/src/Plugins/Qt/QTMWidget.cpp +++ b/src/Plugins/Qt/QTMWidget.cpp @@ -160,25 +160,23 @@ QTMWidget::scrollContentsBy (int dx, int dy) { void QTMWidget::resizeEvent (QResizeEvent* event) { (void) event; - // Is this ok? - // coord2 s = from_qsize (event->size()); - // the_gui -> process_resize (tm_widget(), s.x1, s.x2); - - // the_gui->force_update(); - - // FIXME: I would like to have a force_update here but this causes a failed - // assertion in TeXmacs since the at the boot not every internal structure is - // initialized at this point. It seems not too difficult to fix but I - // postpone this to discuss with Joris. - // - // Not having a force_update results in some lack of sync of the surface - // while the user is actively resizing with the mouse. + // Force update to ensure rendering cache is synchronized with window size + the_gui->force_update (); } void QTMWidget::resizeEventBis (QResizeEvent* event) { coord2 s= from_qsize (event->size ()); the_gui->process_resize (tm_widget (), s.x1, s.x2); + + // Ensure surface size matches the new window size to avoid rendering artifacts + // This is critical for non-integer scaling ratios + QSize new_size= event->size (); + if (surface () && surface ()->size () != new_size) { + surface ()->resize (new_size); + // Force complete redraw after surface resize + tm_widget ()->invalidate_all (); + } } /*! @@ -195,8 +193,11 @@ QTMWidget::paintEvent (QPaintEvent* event) { QImage bs= tm_widget ()->get_backing_store (); QPainter p (surface ()); // this code override the invalid region computations + // Ensure pixel-perfect alignment for both source and destination rectangles + QSize src_size (qCeil (retina_factor * size ().width ()), + qCeil (retina_factor * size ().height ())); p.drawImage (QRect (QPoint (), size ()), bs, - QRect (QPoint (), size () * retina_factor)); + QRect (QPoint (), src_size)); return; } #else @@ -210,11 +211,15 @@ QTMWidget::paintEvent (QPaintEvent* event) { #endif for (int i= 0; i < rects.count (); ++i) { QRect qr= rects.at (i); + // Ensure pixel-perfect alignment for both source and destination rectangles + int src_x = qFloor (retina_factor * qr.x ()); + int src_y = qFloor (retina_factor * qr.y ()); + int src_w = qCeil (retina_factor * (qr.x () + qr.width ())) - src_x; + int src_h = qCeil (retina_factor * (qr.y () + qr.height ())) - src_y; + p.drawPixmap (QRect (qr.x (), qr.y (), qr.width (), qr.height ()), *(tm_widget ()->backingPixmap), - QRect (retina_factor * qr.x (), retina_factor * qr.y (), - retina_factor * qr.width (), - retina_factor * qr.height ())); + QRect (src_x, src_y, src_w, src_h)); } } #endif diff --git a/src/Plugins/Qt/qt_simple_widget.cpp b/src/Plugins/Qt/qt_simple_widget.cpp index c9e5c9204..fb4aa3e90 100644 --- a/src/Plugins/Qt/qt_simple_widget.cpp +++ b/src/Plugins/Qt/qt_simple_widget.cpp @@ -88,6 +88,8 @@ void qt_simple_widget_rep::handle_notify_resize (SI w, SI h) { (void) w; (void) h; + // Force complete redraw when window size changes to avoid rendering artifacts + invalidate_all (); } void @@ -405,14 +407,10 @@ qt_simple_widget_rep::as_qaction () { void qt_simple_widget_rep::invalidate_rect (int x1, int y1, int x2, int y2) { -#ifdef Q_OS_MAC - // HACK: for unknown reasons we need to enlarge the invalid rect to prevent - // artifacts while moving the cursor (for example at the end of a formula like - // $a+f$. These artifacts seems present only on 64 bit Macs. - rectangle r= rectangle (x1 - 10, y1 - 10, x2 + 10, y2 + 10); -#else - rectangle r= rectangle (x1, y1, x2, y2); -#endif + // Enlarge invalid rect to prevent artifacts during zoom and scaling + // This helps with pixel boundary alignment issues + int padding = 2; // Add small padding to ensure complete redraw + rectangle r= rectangle (x1 - padding, y1 - padding, x2 + padding, y2 + padding); // cout << "invalidating " << r << LF; invalid_regions= invalid_regions | rectangles (r); } @@ -465,8 +463,8 @@ qt_simple_widget_rep::repaint_invalid_regions () { // update backing store origin wrt. TeXmacs document if (backing_pos != origin) { - int dx = retina_factor * (origin.x () - backing_pos.x ()); - int dy = retina_factor * (origin.y () - backing_pos.y ()); + int dx = qRound (retina_factor * (origin.x () - backing_pos.x ())); + int dy = qRound (retina_factor * (origin.y () - backing_pos.y ())); backing_pos= origin; QPixmap newBackingPixmap (backingPixmap->size ()); @@ -518,7 +516,8 @@ qt_simple_widget_rep::repaint_invalid_regions () { QSize _oldSize = backingPixmap->size (); QSize _new_logical_Size= canvas ()->surface ()->size (); QSize _newSize = _new_logical_Size; - _newSize*= retina_factor; + _newSize= QSize (qCeil (_new_logical_Size.width () * retina_factor), + qCeil (_new_logical_Size.height () * retina_factor)); // cout << " surface size of " << _newSize.width() << " x " // << _newSize.height() << LF; @@ -569,9 +568,13 @@ qt_simple_widget_rep::repaint_invalid_regions () { while (!is_nil (rects)) { rectangle r = copy (rects->item); rectangle r0= rects->item; - QRect qr= QRect (r0->x1 / retina_factor, r0->y1 / retina_factor, - (r0->x2 - r0->x1) / retina_factor, - (r0->y2 - r0->y1) / retina_factor); + // Ensure pixel-perfect alignment by rounding coordinates consistently + // Use ceil for x2/y2 to ensure we cover the entire area and avoid gaps + int x1_px = qFloor (r0->x1 / retina_factor); + int y1_px = qFloor (r0->y1 / retina_factor); + int x2_px = qCeil (r0->x2 / retina_factor); + int y2_px = qCeil (r0->y2 / retina_factor); + QRect qr= QRect (x1_px, y1_px, x2_px - x1_px, y2_px - y1_px); // cout << "repainting " << r0 << "\n"; ren->set_origin (ox, oy); ren->encode (r->x1, r->y1); -- Gitee From 36eddadb0c7fb9ad66dac652645cda5946d1c7ad Mon Sep 17 00:00:00 2001 From: Yuki Date: Wed, 5 Nov 2025 19:22:39 +0800 Subject: [PATCH 4/5] format --- src/Graphics/Bitmap_fonts/glyph_shrink.cpp | 4 ++-- src/Graphics/Renderer/renderer.cpp | 6 ++++-- src/Plugins/MuPDF/mupdf_qt_simple_widget.cpp | 19 ++++++++++--------- src/Plugins/Qt/QTMWidget.cpp | 15 +++++++-------- src/Plugins/Qt/qt_simple_widget.cpp | 15 ++++++++------- 5 files changed, 31 insertions(+), 28 deletions(-) diff --git a/src/Graphics/Bitmap_fonts/glyph_shrink.cpp b/src/Graphics/Bitmap_fonts/glyph_shrink.cpp index 1dec47d79..59f5d527e 100644 --- a/src/Graphics/Bitmap_fonts/glyph_shrink.cpp +++ b/src/Graphics/Bitmap_fonts/glyph_shrink.cpp @@ -251,8 +251,8 @@ shrink (glyph gl, int xfactor, int yfactor, SI& xo, SI& yo) { return glyph (0, 0, 0, 0, new_depth); } - int tx= ((xfactor / 3) * (int(retina_factor + 0.5) + 1)) / 2; - int ty= ((yfactor / 3) * (int(retina_factor + 0.5) + 1)) / 2; + int tx= ((xfactor / 3) * (int (retina_factor + 0.5) + 1)) / 2; + int ty= ((yfactor / 3) * (int (retina_factor + 0.5) + 1)) / 2; int dx= 0, dy= 0; if ((gl->status == 0) && (xfactor > 1)) dx= get_hor_shift (gl, xfactor, tx); // if ((gl->status==0) && (yfactor>1)) dy= get_ver_shift (gl, yfactor, ty); diff --git a/src/Graphics/Renderer/renderer.cpp b/src/Graphics/Renderer/renderer.cpp index ef981f969..b892adcb2 100644 --- a/src/Graphics/Renderer/renderer.cpp +++ b/src/Graphics/Renderer/renderer.cpp @@ -310,8 +310,10 @@ renderer_rep::decode (SI x, SI y, double& rx, double& ry) { } #define RND(x) \ - (((x) >= 0) ? ((SI) tm_round ((double) (x) / retina_pixel) * retina_pixel) \ - : ((SI) tm_round ((double) ((x) - retina_pixel + 1) / retina_pixel) * retina_pixel)) + (((x) >= 0) \ + ? ((SI) tm_round ((double) (x) / retina_pixel) * retina_pixel) \ + : ((SI) tm_round ((double) ((x) - retina_pixel + 1) / retina_pixel) * \ + retina_pixel)) void renderer_rep::round (SI& x, SI& y) { diff --git a/src/Plugins/MuPDF/mupdf_qt_simple_widget.cpp b/src/Plugins/MuPDF/mupdf_qt_simple_widget.cpp index 5c2baddee..19ceaaeeb 100644 --- a/src/Plugins/MuPDF/mupdf_qt_simple_widget.cpp +++ b/src/Plugins/MuPDF/mupdf_qt_simple_widget.cpp @@ -21,8 +21,9 @@ qt_simple_widget_rep::repaint_invalid_regions () { coord2 pt_or = from_qpoint (backing_pos); coord2 pt_new_or= from_qpoint (origin); - QSize _newSize (qCeil (retina_factor * canvas ()->surface ()->size ().width ()), - qCeil (retina_factor * canvas ()->surface ()->size ().height ())); + QSize _newSize ( + qCeil (retina_factor * canvas ()->surface ()->size ().width ()), + qCeil (retina_factor * canvas ()->surface ()->size ().height ())); bs_ox= -pt_or.x1 * retina_factor; bs_oy= -pt_or.x2 * retina_factor; @@ -86,8 +87,8 @@ qt_simple_widget_rep::repaint_invalid_regions () { } // syncronize all the picture, just to be safe - qrgn+= QRect (QPoint (0, 0), - QSize (qRound (new_bs_w / retina_factor), qRound (new_bs_h / retina_factor))); + qrgn+= QRect (QPoint (0, 0), QSize (qRound (new_bs_w / retina_factor), + qRound (new_bs_h / retina_factor))); // update the state bs_ox = new_bs_ox; @@ -119,11 +120,11 @@ qt_simple_widget_rep::repaint_invalid_regions () { rectangle r0= rects->item; // Ensure pixel-perfect alignment by rounding coordinates consistently // Use ceil for x2/y2 to ensure we cover the entire area and avoid gaps - int x1_px = qFloor (r0->x1 / retina_factor); - int y1_px = qFloor (r0->y1 / retina_factor); - int x2_px = qCeil (r0->x2 / retina_factor); - int y2_px = qCeil (r0->y2 / retina_factor); - QRect qr= QRect (x1_px, y1_px, x2_px - x1_px, y2_px - y1_px); + int x1_px= qFloor (r0->x1 / retina_factor); + int y1_px= qFloor (r0->y1 / retina_factor); + int x2_px= qCeil (r0->x2 / retina_factor); + int y2_px= qCeil (r0->y2 / retina_factor); + QRect qr = QRect (x1_px, y1_px, x2_px - x1_px, y2_px - y1_px); // cout << "repainting " << r0 << "\n"; ren->set_origin (ox, oy); ren->encode (r->x1, r->y1); diff --git a/src/Plugins/Qt/QTMWidget.cpp b/src/Plugins/Qt/QTMWidget.cpp index 624b6abdb..2923e522f 100644 --- a/src/Plugins/Qt/QTMWidget.cpp +++ b/src/Plugins/Qt/QTMWidget.cpp @@ -169,8 +169,8 @@ QTMWidget::resizeEventBis (QResizeEvent* event) { coord2 s= from_qsize (event->size ()); the_gui->process_resize (tm_widget (), s.x1, s.x2); - // Ensure surface size matches the new window size to avoid rendering artifacts - // This is critical for non-integer scaling ratios + // Ensure surface size matches the new window size to avoid rendering + // artifacts This is critical for non-integer scaling ratios QSize new_size= event->size (); if (surface () && surface ()->size () != new_size) { surface ()->resize (new_size); @@ -196,8 +196,7 @@ QTMWidget::paintEvent (QPaintEvent* event) { // Ensure pixel-perfect alignment for both source and destination rectangles QSize src_size (qCeil (retina_factor * size ().width ()), qCeil (retina_factor * size ().height ())); - p.drawImage (QRect (QPoint (), size ()), bs, - QRect (QPoint (), src_size)); + p.drawImage (QRect (QPoint (), size ()), bs, QRect (QPoint (), src_size)); return; } #else @@ -212,10 +211,10 @@ QTMWidget::paintEvent (QPaintEvent* event) { for (int i= 0; i < rects.count (); ++i) { QRect qr= rects.at (i); // Ensure pixel-perfect alignment for both source and destination rectangles - int src_x = qFloor (retina_factor * qr.x ()); - int src_y = qFloor (retina_factor * qr.y ()); - int src_w = qCeil (retina_factor * (qr.x () + qr.width ())) - src_x; - int src_h = qCeil (retina_factor * (qr.y () + qr.height ())) - src_y; + int src_x= qFloor (retina_factor * qr.x ()); + int src_y= qFloor (retina_factor * qr.y ()); + int src_w= qCeil (retina_factor * (qr.x () + qr.width ())) - src_x; + int src_h= qCeil (retina_factor * (qr.y () + qr.height ())) - src_y; p.drawPixmap (QRect (qr.x (), qr.y (), qr.width (), qr.height ()), *(tm_widget ()->backingPixmap), diff --git a/src/Plugins/Qt/qt_simple_widget.cpp b/src/Plugins/Qt/qt_simple_widget.cpp index fb4aa3e90..8934d7431 100644 --- a/src/Plugins/Qt/qt_simple_widget.cpp +++ b/src/Plugins/Qt/qt_simple_widget.cpp @@ -409,8 +409,9 @@ void qt_simple_widget_rep::invalidate_rect (int x1, int y1, int x2, int y2) { // Enlarge invalid rect to prevent artifacts during zoom and scaling // This helps with pixel boundary alignment issues - int padding = 2; // Add small padding to ensure complete redraw - rectangle r= rectangle (x1 - padding, y1 - padding, x2 + padding, y2 + padding); + int padding= 2; // Add small padding to ensure complete redraw + rectangle r= + rectangle (x1 - padding, y1 - padding, x2 + padding, y2 + padding); // cout << "invalidating " << r << LF; invalid_regions= invalid_regions | rectangles (r); } @@ -570,11 +571,11 @@ qt_simple_widget_rep::repaint_invalid_regions () { rectangle r0= rects->item; // Ensure pixel-perfect alignment by rounding coordinates consistently // Use ceil for x2/y2 to ensure we cover the entire area and avoid gaps - int x1_px = qFloor (r0->x1 / retina_factor); - int y1_px = qFloor (r0->y1 / retina_factor); - int x2_px = qCeil (r0->x2 / retina_factor); - int y2_px = qCeil (r0->y2 / retina_factor); - QRect qr= QRect (x1_px, y1_px, x2_px - x1_px, y2_px - y1_px); + int x1_px= qFloor (r0->x1 / retina_factor); + int y1_px= qFloor (r0->y1 / retina_factor); + int x2_px= qCeil (r0->x2 / retina_factor); + int y2_px= qCeil (r0->y2 / retina_factor); + QRect qr = QRect (x1_px, y1_px, x2_px - x1_px, y2_px - y1_px); // cout << "repainting " << r0 << "\n"; ren->set_origin (ox, oy); ren->encode (r->x1, r->y1); -- Gitee From fc00b425dfa03ea74009ad7a98a1986149389ca0 Mon Sep 17 00:00:00 2001 From: Yuki Date: Thu, 6 Nov 2025 17:00:18 +0800 Subject: [PATCH 5/5] wip --- 3rdparty/lolly/Kernel/Abstractions/minmax.hpp | 2 +- src/Graphics/Renderer/renderer.cpp | 87 +++++++++---------- 2 files changed, 43 insertions(+), 46 deletions(-) diff --git a/3rdparty/lolly/Kernel/Abstractions/minmax.hpp b/3rdparty/lolly/Kernel/Abstractions/minmax.hpp index 1690cf08b..9c056d106 100644 --- a/3rdparty/lolly/Kernel/Abstractions/minmax.hpp +++ b/3rdparty/lolly/Kernel/Abstractions/minmax.hpp @@ -7,7 +7,7 @@ #pragma once -typedef int SI; +typedef double SI; typedef unsigned int SN; typedef short HI; typedef unsigned short HN; diff --git a/src/Graphics/Renderer/renderer.cpp b/src/Graphics/Renderer/renderer.cpp index b892adcb2..9ddb074fa 100644 --- a/src/Graphics/Renderer/renderer.cpp +++ b/src/Graphics/Renderer/renderer.cpp @@ -178,31 +178,31 @@ void renderer_rep::set_zoom_factor (double zoom) { if (shrinkf != ((int) tm_round (std_shrinkf / zoomf))) cout << "Invalid zoom " << zoomf << ", " << shrinkf << LF; - ox= (SI) tm_round (ox * zoomf); - oy= (SI) tm_round (oy * zoomf); - // cx1= (SI) ::floor (cx1 * zoomf); - // cx2= (SI) ::floor (cx2 * zoomf); - // cy1= (SI) ::ceil (cy1 * zoomf); - // cy2= (SI) ::ceil (cy2 * zoomf); - cx1 = (SI) tm_round (cx1 * zoomf); - cx2 = (SI) tm_round (cx2 * zoomf); - cy1 = (SI) tm_round (cy1 * zoomf); - cy2 = (SI) tm_round (cy2 * zoomf); + ox= tm_round (ox * zoomf); + oy= tm_round (oy * zoomf); + // cx1= ::floor (cx1 * zoomf); + // cx2= ::floor (cx2 * zoomf); + // cy1= ::ceil (cy1 * zoomf); + // cy2= ::ceil (cy2 * zoomf); + cx1 = tm_round (cx1 * zoomf); + cx2 = tm_round (cx2 * zoomf); + cy1 = tm_round (cy1 * zoomf); + cy2 = tm_round (cy2 * zoomf); zoomf = zoom; shrinkf = (int) tm_round (std_shrinkf / zoomf); thicken = (shrinkf >> 1) * PIXEL; - pixel = (SI) tm_round ((std_shrinkf * PIXEL) / zoomf); + pixel = tm_round ((std_shrinkf * PIXEL) / zoomf); retina_pixel= pixel; - ox = (SI) tm_round (ox / zoomf); - oy = (SI) tm_round (oy / zoomf); - // cx1= (SI) ::floor (cx1 / zoomf); - // cx2= (SI) ::floor (cx2 / zoomf); - // cy1= (SI) ::ceil (cy1 / zoomf); - // cy2= (SI) ::ceil (cy2 / zoomf); - cx1= (SI) tm_round (cx1 / zoomf); - cx2= (SI) tm_round (cx2 / zoomf); - cy1= (SI) tm_round (cy1 / zoomf); - cy2= (SI) tm_round (cy2 / zoomf); + ox = tm_round (ox / zoomf); + oy = tm_round (oy / zoomf); + // cx1= ::floor (cx1 / zoomf); + // cx2= ::floor (cx2 / zoomf); + // cy1= ::ceil (cy1 / zoomf); + // cy2= ::ceil (cy2 / zoomf); + cx1= tm_round (cx1 / zoomf); + cx2= tm_round (cx2 / zoomf); + cy1= tm_round (cy1 / zoomf); + cy2= tm_round (cy2 / zoomf); } void @@ -212,7 +212,7 @@ renderer_rep::reset_zoom_factor () { void renderer_rep::set_shrinking_factor (int sf) { - set_zoom_factor (((double) std_shrinkf) / ((double) sf)); + set_zoom_factor ((std_shrinkf) / (sf)); } void @@ -283,37 +283,36 @@ renderer_rep::is_visible (SI x1, SI y1, SI x2, SI y2) { void renderer_rep::encode (SI& x, SI& y) { - x= (SI) tm_round ((double) x * pixel) - ox; - y= (SI) tm_round ((double) (-y) * pixel) - oy; + x= tm_round (x * pixel) - ox; + y= tm_round ((-y) * pixel) - oy; } void renderer_rep::decode (SI& x, SI& y) { x+= ox; y+= oy; - if (x >= 0) x= (SI) tm_round ((double) x / pixel); - else x= (SI) tm_round ((double) (x - pixel + 1) / pixel); - if (y >= 0) y= -(SI) tm_round ((double) y / pixel); - else y= -(SI) tm_round ((double) (y - pixel + 1) / pixel); + if (x >= 0) x= tm_round (x / pixel); + else x= tm_round ((x - pixel + 1) / pixel); + if (y >= 0) y= -tm_round (y / pixel); + else y= -tm_round ((y - pixel + 1) / pixel); } void renderer_rep::encode (double x, double y, SI& rx, SI& ry) { - rx= (SI) tm_round ((x + 0.5) * pixel) - ox; - ry= (SI) tm_round (((-y) + 0.5) * pixel) - oy; + rx= tm_round ((x + 0.5) * pixel) - ox; + ry= tm_round (((-y) + 0.5) * pixel) - oy; } void renderer_rep::decode (SI x, SI y, double& rx, double& ry) { - rx= ((double) (x + ox)) / pixel - 0.5; - ry= -(((double) (y + oy)) / pixel - 0.5); + rx= (x + ox) / pixel - 0.5; + ry= -((y + oy) / pixel - 0.5); } #define RND(x) \ (((x) >= 0) \ - ? ((SI) tm_round ((double) (x) / retina_pixel) * retina_pixel) \ - : ((SI) tm_round ((double) ((x) - retina_pixel + 1) / retina_pixel) * \ - retina_pixel)) + ? (tm_round ((x) / retina_pixel) * retina_pixel) \ + : (tm_round (((x) - retina_pixel + 1) / retina_pixel) * retina_pixel)) void renderer_rep::round (SI& x, SI& y) { @@ -422,26 +421,24 @@ renderer_rep::clear_pattern (SI mx1, SI my1, SI mx2, SI my2, SI x1, SI y1, url u= b->get_pattern_url (); int imw_pt, imh_pt; image_size (u, imw_pt, imh_pt); - double pt = ((double) 600 * PIXEL) / 72.0; - SI imw = (SI) (((double) imw_pt) * pt); - SI imh = (SI) (((double) imh_pt) * pt); - double ratio= ((double) max (imw_pt, 1)) / ((double) max (imh_pt, 1)); + double pt = (600 * PIXEL) / 72.0; + SI imw = imw_pt * pt; + SI imh = imh_pt * pt; + double ratio= max (imw_pt, 1) / max (imh_pt, 1); bool flag= false; SI w= mx2 - mx1, h= my2 - my1; if (pattern[1] == "") w= imw; else if (is_int (pattern[1])) w= as_int (pattern[1]); - else if (is_percentage (pattern[1])) - w= (SI) (as_percentage (pattern[1]) * ((double) w)); + else if (is_percentage (pattern[1])) w= as_percentage (pattern[1]) * w; else flag= true; if (pattern[1] == "") h= imh; else if (is_int (pattern[2])) h= as_int (pattern[2]); - else if (is_percentage (pattern[2])) - h= (SI) (as_percentage (pattern[2]) * ((double) h)); + else if (is_percentage (pattern[2])) h= as_percentage (pattern[2]) * h; else if (is_percentage (pattern[2], "@")) - h= (SI) (as_percentage (pattern[2]) * ((double) w) / ratio); + h= as_percentage (pattern[2]) * w / ratio; if (flag && is_percentage (pattern[1], "@")) - w= (SI) (as_percentage (pattern[1]) * ((double) h) * ratio); + w= as_percentage (pattern[1]) * h * ratio; w= ((w + pixel - 1) / pixel) * pixel; h= ((h + pixel - 1) / pixel) * pixel; -- Gitee