From 4957a90aeb4075f60b56aa7cd4eab8a75385f2a9 Mon Sep 17 00:00:00 2001
From: Kensuke Matsuzaki
Date: Fri, 21 Feb 2025 22:44:30 +0900
Subject: [PATCH 1/2] =?UTF-8?q?[js]=E3=83=95=E3=82=A9=E3=83=B3=E3=83=88?=
=?UTF-8?q?=E5=87=A6=E7=90=86=E3=82=92=E4=BF=AE=E6=AD=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
テキストのサイズ計測でリフローが発生しないようにdivをやめてmeasureTextに統一する
太文字とイタリックのスタイルを反映する
フォント名指定でクオートしない
フォントキャッシュでフォントを考慮する
フォントテクスチャに余白を追加
---
src/hsp3dish/emscripten/fontsystem.cpp | 129 ++++++++++++-------------
src/hsp3dish/emscripten/hgiox.cpp | 15 +++
src/hsp3dish/texmes.cpp | 4 +-
src/hsp3dish/texmes.h | 1 +
4 files changed, 81 insertions(+), 68 deletions(-)
diff --git a/src/hsp3dish/emscripten/fontsystem.cpp b/src/hsp3dish/emscripten/fontsystem.cpp
index a015e822..33d9d465 100644
--- a/src/hsp3dish/emscripten/fontsystem.cpp
+++ b/src/hsp3dish/emscripten/fontsystem.cpp
@@ -58,6 +58,7 @@
#define USE_JAVA_FONT
#define FONT_TEX_SX 512
#define FONT_TEX_SY 128
+#define FONT_PADDING 1
#endif
#if defined(HSPLINUX) || defined(HSPEMSCRIPTEN)
@@ -741,12 +742,14 @@ int hgio_fontsystem_exec(char* msg, unsigned char* buffer, int pitch, int* out_s
#if defined(HSPEMSCRIPTEN)
#ifndef USE_TTFFONT
+#define HSPJS_DEFAULT_FONTNAME "sans-serif"
static int fontsystem_flag = 0;
static int fontsystem_sx; // 横のサイズ
static int fontsystem_sy; // 縦のサイズ
static unsigned char *fontdata_pix;
static int fontdata_size;
static int fontdata_color;
+static std::string fontsystem_fontname = HSPJS_DEFAULT_FONTNAME;
static int fontsystem_size;
static int fontsystem_style;
static int fontsystem_texid;
@@ -775,6 +778,9 @@ void hgio_fontsystem_init(char* fontname, int size, int style)
// フォントレンダリング初期化
//
hgio_fontsystem_term();
+ if (fontname != NULL && *fontname != 0) {
+ fontsystem_fontname = fontname;
+ }
fontsystem_flag = 1;
fontsystem_size = size;
fontsystem_style = style;
@@ -786,56 +792,50 @@ int hgio_fontsystem_exec(char* msg, unsigned char* buffer, int pitch, int* out_s
// (bufferがNULLの場合はサイズだけを取得する)
//
+ EM_ASM_({
+ let canvas = document.getElementById('hsp3dishFontCanvas');
+ if (!canvas) {
+ canvas = document.createElement("canvas");
+ canvas.id = 'hsp3dishFontCanvas';
+ canvas.style.setProperty("visibility", "hidden");
+ canvas.style.setProperty("position", "absolute");
+ canvas.style.setProperty("top", "0");
+ canvas.style.setProperty("left", "0");
+ document.body.appendChild(canvas);
+ }
+ });
+
if (buffer == NULL) {
EM_ASM_({
- let d = document.getElementById('hsp3dishFontDiv');
- if (!d) {
- d = document.createElement("div");
- d.id = 'hsp3dishFontDiv';
- d.style.setProperty("width", "auto");
- d.style.setProperty("height", "auto");
- d.style.setProperty("position", "absolute");
- d.style.setProperty("visibility", "hidden");
- d.style.setProperty("top", "0");
- d.style.setProperty("left", "0");
- document.body.appendChild(d);
- }
- d.style.setProperty("font", $1 + "px 'sans-serif'");
-
- //const t = document.createTextNode(UTF8ToString($0));
- //if (d.hasChildNodes())
- // d.removeChild(d.firstChild);
- //d.appendChild(t);
- d.innerText = UTF8ToString($0);
- HEAP32[$2 >> 2] = d.clientWidth | 0;
- HEAP32[$3 >> 2] = d.clientHeight | 0;
-
- let canvas = document.getElementById('hsp3dishFontCanvas');
- if (!canvas) {
- canvas = document.createElement("canvas");
- canvas.id = 'hsp3dishFontCanvas';
- canvas.style.setProperty("visibility", "hidden");
- document.body.appendChild(canvas);
- }
-
- if ($4 != 0) {
- const context = canvas.getContext("2d");
- context.font = $1 + "px 'sans-serif'";
-
- const msg = UTF8ToString($0);
- const metrics = context.measureText(msg);
+ const canvas = document.getElementById('hsp3dishFontCanvas');
+ const context = canvas.getContext("2d", { willReadFrequently: true });
+ const msg = UTF8ToString($0);
+ const fontname = UTF8ToString($1);
+ const fontsize = $2;
+
+ let fontStyle = "";
+ if ($3 & 1) fontStyle += "bold ";
+ if ($3 & 2) fontStyle += "italic ";
+ const leading_scale = Number(ENV.HSP_FONT_LEADING) || 1.1;
+ fontStyle += Math.round($2 / leading_scale) + "px " + fontname;
+ context.font = fontStyle;
+ // console.log("measure char", fontStyle);
+
+ const metrics = context.measureText(msg);
+ HEAP32[$4 >> 2] = Math.ceil(Math.max(metrics.width, metrics.actualBoundingBoxRight) - Math.min(0, metrics.actualBoundingBoxLeft)) + 1;
+ HEAP32[$5 >> 2] = fontsize * 2;
+
+ if ($6 !== 0) {
//console.log({msg, metrics});
const arr = Array.from(msg);
for (let i = 0; i < msg.length; i++) {
const sub = arr.slice(0, i + 1).join("");
const m = context.measureText(sub);
//console.log({i, sub, m});
- HEAP16[($4 >> 1) + i + 1] = m.width | 0; //(m.actualBoundingBoxRight - m.actualBoundingBoxLeft) | 0;
+ HEAP16[($6 >> 1) + i + 1] = m.width | 0; //(m.actualBoundingBoxRight - m.actualBoundingBoxLeft) | 0;
}
}
- }, msg, fontsystem_size, & fontsystem_sx, & fontsystem_sy, info ? info->pos : nullptr);
-
- //Alertf("text %s %d %d\n", msg, fontsystem_sx, fontsystem_sy);
+ }, msg, fontsystem_fontname.c_str(), fontsystem_size, fontsystem_style, &fontsystem_sx, &fontsystem_sy, info ? info->pos : nullptr);
*out_sx = fontsystem_sx;
*out_sy = fontsystem_sy;
@@ -847,38 +847,33 @@ int hgio_fontsystem_exec(char* msg, unsigned char* buffer, int pitch, int* out_s
int sy = Get2N(fontsystem_sy);
EM_ASM_({
- var canvas = document.getElementById('hsp3dishFontCanvas');
- if (!canvas) {
- //document.body.removeChild(canvas);
- canvas = document.createElement("canvas");
- canvas.id = 'hsp3dishFontCanvas';
- canvas.style.setProperty("visibility", "hidden");
- canvas.style.setProperty("position", "absolute");
- canvas.style.setProperty("top", "0");
- canvas.style.setProperty("left", "0");
- canvas.width = $2;
- canvas.height = $3;
- document.body.appendChild(canvas);
- }
- if (canvas.width < $2)
- canvas.width = $2;
- if (canvas.height < $3)
- canvas.height = $3;
-
- var context = canvas.getContext("2d", { willReadFrequently: true });
- context.font = $1 + "px 'sans-serif'";
-
- var msg = UTF8ToString($0);
- context.clearRect(0, 0, Math.min(canvas.width, $2 + 1), Math.min(canvas.height, $3 + 1));
+ const canvas = document.getElementById('hsp3dishFontCanvas');
+ if (canvas.width < $4)
+ canvas.width = $4;
+ if (canvas.height < $5)
+ canvas.height = $5;
+ const context = canvas.getContext("2d", { willReadFrequently: true });
+ const msg = UTF8ToString($0);
+ const fontname = UTF8ToString($1);
+ const fontsize = $2;
+
+ let fontStyle = "";
+ if ($3 & 1) fontStyle += "bold ";
+ if ($3 & 2) fontStyle += "italic ";
+ const leading_scale = Number(ENV.HSP_FONT_LEADING) || 1.1;
+ fontStyle += Math.round($2 / leading_scale) + "px " + fontname;
+ context.font = fontStyle;
+
+ context.clearRect(0, 0, Math.min(canvas.width, $4 + 1), Math.min(canvas.height, $5 + 1));
context.fillStyle = 'rgba(255, 255, 255, 255)';
- context.fillText(msg, 0, $1);
+ context.fillText(msg, 0, Math.floor(fontsize * 1.5));
//console.log(msg);
//GLctx.texImage2D(GLctx.TEXTURE_2D, 0, GLctx.RGBA, GLctx.RGBA, GLctx.UNSIGNED_BYTE, context.getImageData(0, 0, $2, $3));
- var imageData = context.getImageData(0, 0, $2, $3);
- HEAPU8.set(imageData.data, $4);
+ var imageData = context.getImageData(0, 0, $4, $5);
+ HEAPU8.set(imageData.data, $6);
- }, msg, fontsystem_size, sx, sy, buffer);
+ }, msg, fontsystem_fontname.c_str(), fontsystem_size, fontsystem_style, sx, sy, buffer);
//Alertf( "Init:Surface(%d,%d) %d destpitch%d",fontsystem_sx,fontsystem_sy,fontdata_color,pitch );
*out_sx = fontsystem_sx;
diff --git a/src/hsp3dish/emscripten/hgiox.cpp b/src/hsp3dish/emscripten/hgiox.cpp
index bac7b6d9..46ec0df7 100755
--- a/src/hsp3dish/emscripten/hgiox.cpp
+++ b/src/hsp3dish/emscripten/hgiox.cpp
@@ -19,12 +19,14 @@
#ifdef HSPWIN
#define STRICT
#include
+#define FONT_PADDING 0
#endif
#ifdef HSPNDK
#define USE_JAVA_FONT
#define FONT_TEX_SX 512
#define FONT_TEX_SY 128
+#define FONT_PADDING 0
#include "../../appengine.h"
#include "../../javafunc.h"
#include "font_data.h"
@@ -37,6 +39,7 @@
#include
#include "iOSBridge.h"
#include "hsp3dish/ios/appengine.h"
+#define FONT_PADDING 0
#endif
@@ -46,6 +49,7 @@
#define USE_JAVA_FONT
#define FONT_TEX_SX 512
#define FONT_TEX_SY 128
+#define FONT_PADDING 0
//#include "font_data.h"
#endif
@@ -58,6 +62,7 @@
#define USE_JAVA_FONT
#define FONT_TEX_SX 512
#define FONT_TEX_SY 128
+#define FONT_PADDING 1
#endif
#if defined(HSPLINUX) || defined(HSPEMSCRIPTEN)
@@ -2021,6 +2026,8 @@ int hgio_mes(BMSCR* bm, char* msg)
return 0;
}
+ int fontsize = tmes._fontsize;
+
int id;
texmes* tex;
id = tmes.texmesRegist(msg);
@@ -2046,11 +2053,19 @@ int hgio_mes(BMSCR* bm, char* msg)
bm->printoffsety = 0;
}
+#if FONT_PADDING == 0
hgio_fontcopy(bm, bm->cx, bm->cy, tex->ratex, tex->ratey, xsize, ysize, tex->_texture, 0, 0);
if (xsize > bm->printsizex) bm->printsizex = xsize;
bm->printsizey += ysize;
bm->cy += ysize;
+#else
+ hgio_fontcopy(bm, bm->cx, bm->cy - fontsize / 2, tex->ratex, tex->ratey, xsize, ysize, tex->_texture, 0, 0);
+
+ if (xsize > bm->printsizex) bm->printsizex = xsize;
+ bm->printsizey += fontsize;
+ bm->cy += fontsize;
+#endif
return 0;
}
diff --git a/src/hsp3dish/texmes.cpp b/src/hsp3dish/texmes.cpp
index 03f39ea2..38e9a8cf 100644
--- a/src/hsp3dish/texmes.cpp
+++ b/src/hsp3dish/texmes.cpp
@@ -95,6 +95,7 @@ void texmes::reset(int width, int height, int p_texsx, int p_texsy, void* data)
life = TEXMES_CACHE_DEFAULT;
font_size = 0;
font_style = 0;
+ fontname = "";
if (text != NULL) text[0] = 0;
buf[0] = 0;
texmespos = NULL;
@@ -246,7 +247,7 @@ int texmesManager::texmesGetCache(char* msg, short mycache, texmesPos* info)
for (i = 0; i < _maxtexmes; i++) {
if (t->flag) { // 使用中だった時
if (t->hash == mycache) { // まずハッシュを比べる
- if (t->font_size == _fontsize && t->font_style == _fontstyle) { // サイズ・スタイルを比べる
+ if (t->font_size == _fontsize && t->font_style == _fontstyle && t->fontname == _fontname) { // サイズ・スタイル・フォントを比べる
bool found = true;
if (info) {
if (info != t->texmespos) { // 異なるtexmesPosはキャッシュしない
@@ -372,6 +373,7 @@ int texmesManager::texmesRegist(char* msg, texmesPos *info)
tex->hash = mycache;
tex->font_size = _fontsize;
tex->font_style = _fontstyle;
+ tex->fontname = _fontname;
tex->texmespos = info;
return tex->entry;
diff --git a/src/hsp3dish/texmes.h b/src/hsp3dish/texmes.h
index 49f9504f..c279d287 100644
--- a/src/hsp3dish/texmes.h
+++ b/src/hsp3dish/texmes.h
@@ -44,6 +44,7 @@ class texmes {
int hash; // Text Hashcode
int life; // Text Cache life
char* text; // Long Text Message
+ std::string fontname; // Fontname
int textsize; // Long Text Message size
int font_size; // Text font size
int font_style; // Text font style
From 5f0d50891ed208defe6437b896371db361d7338b Mon Sep 17 00:00:00 2001
From: Kensuke Matsuzaki
Date: Thu, 28 Aug 2025 19:10:59 +0900
Subject: [PATCH 2/2] =?UTF-8?q?hsp3dish.js=E9=96=A2=E9=80=A3=E3=81=AE?=
=?UTF-8?q?=E3=83=89=E3=82=AD=E3=83=A5=E3=83=A1=E3=83=B3=E3=83=88=E3=82=92?=
=?UTF-8?q?=E8=BF=BD=E5=8A=A0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
doclib/hsp3dish_js.htm | 13 +++++++++++++
doclib_en/hsp3dish_js.htm | 12 ++++++++++++
2 files changed, 25 insertions(+)
diff --git a/doclib/hsp3dish_js.htm b/doclib/hsp3dish_js.htm
index 7d5506fa..b7b9d1e9 100644
--- a/doclib/hsp3dish_js.htm
+++ b/doclib/hsp3dish_js.htm
@@ -28,6 +28,7 @@ hsp3dish.js (WebGL/html5版)
プログラミングガイド
メディアファイルの再生
exec,dialog命令によるブラウザ制御
センサー情報の取得(New!)
+ データ保存
制限事項・既知の問題点
今後の予定
ライセンス・謝辞
@@ -184,6 +185,9 @@ 表示サイズのスケーリング
ENV.HSP_AUTOSCALE = "0";//スケーリングモード
ENV.HSP_FPS = "0";//フレームレート
ENV.HSP_LIMIT_STEP = "15000";//ブラウザに処理を返すまでの実行ステップ数
+ ENV.HSP_FONT_LEADING = "1.1";//フォントの行間調整(1.0=余白無し,1.1=標準,1.2=少し広め)
+ ENV.HSP_KEYBOARD_ELEMENT = null;//キーボード入力対象要素(null=ウィンドウ全体,または要素IDを"#canvas"などのように指定)
+ ENV.HSP_SYNC_DIR = null;//IndexDBで永続化するディレクトリ
});
@@ -283,6 +287,15 @@
センサー情報の取得
+ データ保存
+
+ 基本的にはhsp3dish.jsでは、notesave命令やbsave命令などはメモリ上でエミュレートされ、ブラウザを閉じると消えてしまいます。
+ hsp3dish.jsでの拡張としてIndexDBを使用して、データを永続化することも可能です。
+ ENV.HSP_SYNC_DIRに保存するディレクトリ名を指定し、devcontrol "syncfs"を呼び出すことで、指定したディレクトリ以下のデータをIndexedDBに保存することができます。
+ 保存されたデータは、ブラウザを閉じても残りますので、次回起動時に復元されます。
+
+
+
制限事項・既知の問題点
現在のバージョンでは、以下の制限事項があります。
diff --git a/doclib_en/hsp3dish_js.htm b/doclib_en/hsp3dish_js.htm
index fedfa480..9236ff4a 100644
--- a/doclib_en/hsp3dish_js.htm
+++ b/doclib_en/hsp3dish_js.htm
@@ -28,6 +28,7 @@
hsp3dish.js (WebGL/html5 Version)
Programming Guide
Media File Playback
Browser Control with exec, dialog Commands
Acquiring Sensor Information (New!)
+ Data Storage
Restrictions/Known Issues
Future Plans
License/Acknowledgements
@@ -184,6 +185,8 @@ Scaling Display Size
ENV.HSP_AUTOSCALE = "0";//Scaling mode
ENV.HSP_FPS = "0";//Frame rate
ENV.HSP_LIMIT_STEP = "15000";//Number of execution steps before returning processing to the browser
+ ENV.HSP_FONT_LEADING = "1.1";//Font line spacing adjustment (1.0=No margin, 1.1=Standard, 1.2=A little wider)
+ ENV.HSP_KEYBOARD_ELEMENT = null;//Keyboard input target element (null=whole window, or specify an element ID like "#canvas")
});
@@ -281,6 +284,15 @@
Acquiring Sensor Information
+ Data Storage
+
+ Basically, in hsp3dish.js, commands such as notesave and bsave are emulated in memory and will disappear when the browser is closed.
+ As an extension in hsp3dish.js, it is also possible to persist data using IndexedDB.
+ By specifying the directory name to save in ENV.HSP_SYNC_DIR and calling devcontrol "syncfs", you can save data under the specified directory to IndexedDB.
+ The saved data will remain even after closing the browser, so it will be restored the next time you start up.
+
+
+
Restrictions and Known Issues
The current version has the following restrictions.