From 37aef2ecc88a747da548a6a5cc87e36c44de865d Mon Sep 17 00:00:00 2001
From: Willem Dantuma <willem.dantuma@dobs.nl>
Date: Thu, 25 Jul 2024 08:33:21 +0200
Subject: [PATCH] Improve memory usage (#176)

---
 src/app/modules/map/ol/lib/s57.service.ts |  11 ++-
 src/app/modules/map/ol/lib/s57Style.ts    | 114 ++++++++++++----------
 2 files changed, 71 insertions(+), 54 deletions(-)

diff --git a/src/app/modules/map/ol/lib/s57.service.ts b/src/app/modules/map/ol/lib/s57.service.ts
index 5448cbef..9beeabe2 100644
--- a/src/app/modules/map/ol/lib/s57.service.ts
+++ b/src/app/modules/map/ol/lib/s57.service.ts
@@ -4,7 +4,7 @@ import { HttpClient } from '@angular/common/http';
 import { Feature } from 'ol';
 import { Subject } from 'rxjs';
 import * as xml2js from 'xml2js';
-import { Point } from 'ol/geom';
+import { Style  } from 'ol/style';
 
 interface Symbol {
   image: HTMLImageElement;
@@ -99,6 +99,7 @@ export class S57Service {
   private chartSymbolsImage: HTMLImageElement;
   private lookups: Lookup[] = [];
   private lookupStartIndex: Map<string, number> = new Map<string, number>();
+  private styles: Map<string, Style> = new Map<string, Style>();
   public refresh: Subject<void> = new Subject<void>();
 
   //options
@@ -129,6 +130,14 @@ export class S57Service {
       });
   }
 
+  public getStyle(key:string):Style {
+    return this.styles[key]
+  }
+
+  public setStyle(key:string,style:Style) {
+    this.styles[key]=style
+  }
+
   // eslint-disable-next-line @typescript-eslint/no-explicit-any
   private isChanged(currentValue: any, newValue: any): boolean {
     let changed = false;
diff --git a/src/app/modules/map/ol/lib/s57Style.ts b/src/app/modules/map/ol/lib/s57Style.ts
index 52455fde..374bcb63 100644
--- a/src/app/modules/map/ol/lib/s57Style.ts
+++ b/src/app/modules/map/ol/lib/s57Style.ts
@@ -36,12 +36,7 @@ export class S57Style {
   }
 
   //TODO implement more parameters
-  private getTextStyle(text: string, params: string[]): Style {
-    if (typeof text !== 'string') {
-      //debugger;
-      return null;
-    }
-
+  private getTextStyle(params: string[]): Style {
     // eslint-disable-next-line @typescript-eslint/no-explicit-any
     let textBaseline: any = 'middle';
     let offsetY = 0;
@@ -64,52 +59,51 @@ export class S57Style {
       offsetX = 0;
     }
 
-    if (text) {
-      let tx = text;
-      if (typeof tx !== 'string') {
-        tx = text.toString();
-      }
-      const style = new Style({
-        text: new Text({
-          text: tx,
-          textAlign: textAlign,
-          textBaseline: textBaseline,
-          scale: 1.5,
-          offsetX: offsetX,
-          offsetY: offsetY
-        })
-      });
-      style.setZIndex(99); // text always on top
-      return style;
-    }
-    return null;
+    const style = new Style({
+      text: new Text({
+        textAlign: textAlign,
+        textBaseline: textBaseline,
+        scale: 1.5,
+        offsetX: offsetX,
+        offsetY: offsetY,
+      })
+    });
+    style.setZIndex(99); // text always on top
+    return style
+
   }
 
   // eslint-disable-next-line @typescript-eslint/no-explicit-any
-  private getTextStyleTX(featureProperties: any, parameters: string): Style {
+  private getTextStyleTXStyle(featureProperties: any, parameters: string): Style {
+    const params = parameters.split(',');
+    return this.getTextStyle(params.slice(1));
+  }
+
+  private getTextStyleTXText(featureProperties: any, parameters: string): string {
     const params = parameters.split(',');
     const text = featureProperties[params[0]];
-    if (!text) {
-      return null;
-    }
-    return this.getTextStyle(text, params.slice(1));
+    return text
   }
 
   private stripQuotes(text: string): string {
     return text.substring(1).substring(0, text.length - 2);
   }
 
-  //TODO format string
+
   // eslint-disable-next-line @typescript-eslint/no-explicit-any
-  private getTextStyleTE(featureProperties: any, parameters: string): Style {
+  private getTextStyleTEText(featureProperties: any, parameters: string): string {
     const params = parameters.split(',');
     const text = featureProperties[this.stripQuotes(params[1])];
     const format = this.stripQuotes(params[0]);
     if (!text || !format) {
       return null;
     }
-    const formatted = format.replace(/%[0-9]*.?[0-9]*l?[sfd]/, text);
-    return this.getTextStyle(formatted, params.slice(2));
+    return format.replace(/%[0-9]*.?[0-9]*l?[sfd]/, text);
+  }
+
+  private getTextStyleTEStyle(featureProperties: any, parameters: string): Style {
+    const params = parameters.split(',');
+    return this.getTextStyle(params.slice(2));
   }
 
   private getDefaultStyle(): Style {
@@ -743,6 +737,7 @@ export class S57Style {
     return retval;
   }
 
+
   private getStylesFromRules(lup: Lookup, feature: Feature): Style[] {
     const styles: Style[] = [];
     if (lup) {
@@ -761,26 +756,39 @@ export class S57Style {
         const instrParts = this.instructionMatch.exec(instruction);
         if (instrParts && instrParts.length > 1) {
           let style: Style = null;
-          switch (instrParts[1]) {
-            case 'SY':
-              style = this.getSymbolStyle(instrParts[2]);
-              break;
-            case 'AC':
-              style = this.getAreaStyle(instrParts[2]);
-              break;
-            case 'TX':
-              style = this.getTextStyleTX(properties, instrParts[2]);
-              break;
-            case 'TE':
-              style = this.getTextStyleTE(properties, instrParts[2]);
-              break;
-            case 'LS':
-              style = this.getLineStyle(instrParts[2]);
-              break;
-            default:
-              console.debug('Unsupported instruction:' + instruction);
+          let cacheKey = instrParts[1] + "_" + instrParts[2]         
+          style = this.s57Service.getStyle(cacheKey)
+          if (!style) {
+            switch (instrParts[1]) {
+              case 'SY':
+                style = this.getSymbolStyle(instrParts[2]);
+                break;
+              case 'AC':
+                style = this.getAreaStyle(instrParts[2]);
+                break;
+              case 'TX':
+                style = this.getTextStyleTXStyle(properties, instrParts[2]);
+                break;
+              case 'TE':
+                style = this.getTextStyleTEStyle(properties, instrParts[2]);
+                break;
+              case 'LS':
+                style = this.getLineStyle(instrParts[2]);
+                break;
+              default:
+                debugger
+                console.debug('Unsupported instruction:' + instruction);
+            }
+            this.s57Service.setStyle(cacheKey, style)
           }
-          if (style !== null) {
+
+          if (style) {
+            if(instrParts[1]=="TE") {
+              style.getText().setText(this.getTextStyleTEText(properties,instrParts[2]))
+            }
+            if(instrParts[1]=="TX") {
+              style.getText().setText(this.getTextStyleTXText(properties,instrParts[2]))
+            }
             styles.push(style);
           }
         }