@@ -15,6 +15,9 @@ const PMI_EXPORT_CAPTURE_WIDTH_PX = 2400;
1515const PMI_EXPORT_CAPTURE_HEIGHT_PX = 1800 ;
1616const DEFAULT_PMI_VIEW_TEXT_SIZE_PT = 12 ;
1717const SVG_NS = 'http://www.w3.org/2000/svg' ;
18+ const CSS_COLOR_RE = / ^ # [ 0 - 9 a - f ] { 3 , 8 } $ / i;
19+ const CSS_FUNCTION_COLOR_RE = / ^ ( r g b | r g b a | h s l | h s l a ) \( [ ^ ) ] + \) $ / i;
20+ const CSS_NAMED_COLOR_RE = / ^ [ a - z A - Z ] + $ / ;
1821
1922export class PMIViewsWidget {
2023 constructor ( viewer , { readOnly = false } = { } ) {
@@ -309,6 +312,21 @@ export class PMIViewsWidget {
309312 return this . _isMonochromeExport ( renderContext ) && renderContext ?. showCenterLines === true ;
310313 }
311314
315+ _normalizeExportBackdropColor ( color , fallback = null ) {
316+ const text = String ( color ?? '' ) . trim ( ) ;
317+ if ( ! text ) return fallback ;
318+ if ( / ^ t r a n s p a r e n t $ / i. test ( text ) ) return null ;
319+ if ( CSS_COLOR_RE . test ( text ) || CSS_FUNCTION_COLOR_RE . test ( text ) || CSS_NAMED_COLOR_RE . test ( text ) ) {
320+ return text ;
321+ }
322+ return fallback ;
323+ }
324+
325+ _getMonochromeLabelBackdropColor ( renderContext = null ) {
326+ if ( ! this . _isMonochromeExport ( renderContext ) ) return null ;
327+ return this . _normalizeExportBackdropColor ( renderContext ?. labelBackdropColor , null ) ;
328+ }
329+
312330 _createTransparentImageDataUrl ( width , height ) {
313331 const canvas = document . createElement ( 'canvas' ) ;
314332 canvas . width = Math . max ( 1 , Number ( width ) || 1 ) ;
@@ -711,19 +729,20 @@ export class PMIViewsWidget {
711729 fontSize,
712730 layout,
713731 } = layoutData ;
732+ const monochromeBackdrop = this . _getMonochromeLabelBackdropColor ( renderContext ) ;
714733
715734 for ( const entry of layout ) {
716- if ( ! isMonochrome ) {
735+ if ( ! isMonochrome || monochromeBackdrop ) {
717736 const rect = document . createElementNS ( SVG_NS , 'rect' ) ;
718737 rect . setAttribute ( 'x' , entry . x . toFixed ( 3 ) ) ;
719738 rect . setAttribute ( 'y' , entry . y . toFixed ( 3 ) ) ;
720739 rect . setAttribute ( 'rx' , String ( radius ) ) ;
721740 rect . setAttribute ( 'ry' , String ( radius ) ) ;
722741 rect . setAttribute ( 'width' , entry . boxWidth . toFixed ( 3 ) ) ;
723742 rect . setAttribute ( 'height' , entry . boxHeight . toFixed ( 3 ) ) ;
724- rect . setAttribute ( 'fill' , 'rgba(17,24,39,0.92)' ) ;
725- rect . setAttribute ( 'stroke' , '#111827' ) ;
726- rect . setAttribute ( 'stroke-width' , '1' ) ;
743+ rect . setAttribute ( 'fill' , isMonochrome ? monochromeBackdrop : 'rgba(17,24,39,0.92)' ) ;
744+ rect . setAttribute ( 'stroke' , isMonochrome ? 'none' : '#111827' ) ;
745+ rect . setAttribute ( 'stroke-width' , isMonochrome ? '0' : '1' ) ;
727746 labelGroup . appendChild ( rect ) ;
728747 }
729748
@@ -995,6 +1014,7 @@ export class PMIViewsWidget {
9951014 viewport,
9961015 renderMode,
9971016 showCenterLines,
1017+ labelBackdropColor : this . _normalizeExportBackdropColor ( options ?. labelBackdropColor , null ) ,
9981018 targetFrameWidthIn : Number ( options ?. targetFrameWidthIn ) > 0 ? Number ( options . targetFrameWidthIn ) : null ,
9991019 targetFrameHeightIn : Number ( options ?. targetFrameHeightIn ) > 0 ? Number ( options . targetFrameHeightIn ) : null ,
10001020 dispose : ( ) => {
@@ -1459,6 +1479,7 @@ export class PMIViewsWidget {
14591479 hideViewCube = true ,
14601480 renderMode = 'shaded' ,
14611481 showCenterLines = false ,
1482+ labelBackdropColor = null ,
14621483 targetFrameWidthIn = null ,
14631484 targetFrameHeightIn = null ,
14641485 } = { } ) {
@@ -1470,6 +1491,7 @@ export class PMIViewsWidget {
14701491 const renderContext = this . _createExportRenderContext ( captureViewport , view , {
14711492 renderMode,
14721493 showCenterLines,
1494+ labelBackdropColor,
14731495 targetFrameWidthIn,
14741496 targetFrameHeightIn,
14751497 } ) ;
@@ -1609,8 +1631,7 @@ export class PMIViewsWidget {
16091631 this . _applyView ( v , { index : idx } ) ;
16101632 return ;
16111633 }
1612- this . _enterEditMode ( v , idx ) ;
1613- setTimeout ( ( ) => this . _enterEditMode ( v , idx ) , 200 ) ;
1634+ this . enterEditMode ( v , idx ) ;
16141635 } ) ;
16151636 row . appendChild ( nameButton ) ;
16161637
@@ -2275,8 +2296,12 @@ export class PMIViewsWidget {
22752296 }
22762297
22772298 const escape = ( s ) => this . _escapeXML ( String ( s ) ) ;
2299+ const monochromeBackdrop = this . _getMonochromeLabelBackdropColor ( renderContext ) ;
22782300 const rects = isMonochrome
2279- ? ''
2301+ ? ( monochromeBackdrop
2302+ ? layout . map ( ( { x, y, boxWidth, boxHeight } ) =>
2303+ `<rect x="${ x . toFixed ( 3 ) } " y="${ y . toFixed ( 3 ) } " rx="${ radius } " ry="${ radius } " width="${ boxWidth . toFixed ( 3 ) } " height="${ boxHeight . toFixed ( 3 ) } " fill="${ escape ( monochromeBackdrop ) } " stroke="none" stroke-width="0"/>` ) . join ( '' )
2304+ : '' )
22802305 : layout . map ( ( { x, y, boxWidth, boxHeight } ) =>
22812306 `<rect x="${ x . toFixed ( 3 ) } " y="${ y . toFixed ( 3 ) } " rx="${ radius } " ry="${ radius } " width="${ boxWidth . toFixed ( 3 ) } " height="${ boxHeight . toFixed ( 3 ) } " fill="rgba(17,24,39,0.92)" stroke="#111827" stroke-width="1"/>` ) . join ( '' ) ;
22822307
@@ -2687,6 +2712,11 @@ export class PMIViewsWidget {
26872712 try { this . viewer . startPMIMode ?. ( view , index , this , { fromViewClick : true } ) ; } catch { }
26882713 }
26892714
2715+ enterEditMode ( view , index ) {
2716+ this . _enterEditMode ( view , index ) ;
2717+ setTimeout ( ( ) => this . _enterEditMode ( view , index ) , 200 ) ;
2718+ }
2719+
26902720 // --- Helpers: view settings ---
26912721 _isFaceObject ( obj ) {
26922722 return ! ! obj && ( obj . type === 'FACE' || ( obj . isMesh && typeof obj . userData ?. faceName === 'string' ) ) ;
0 commit comments