mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-11-16 01:21:16 +01:00
fix font issue when missing
This commit is contained in:
parent
b5da272dbd
commit
ec0ae36a82
@ -2595,7 +2595,6 @@ public class PdfJsonConversionService {
|
|||||||
PDPageContentStream contentStream, PdfJsonTextColor color, boolean nonStroking)
|
PDPageContentStream contentStream, PdfJsonTextColor color, boolean nonStroking)
|
||||||
throws IOException {
|
throws IOException {
|
||||||
if (color == null || color.getComponents() == null) {
|
if (color == null || color.getComponents() == null) {
|
||||||
log.trace("[ColorApply] Skipping null color for nonStroking={}", nonStroking);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
float[] components = new float[color.getComponents().size()];
|
float[] components = new float[color.getComponents().size()];
|
||||||
@ -2603,11 +2602,6 @@ public class PdfJsonConversionService {
|
|||||||
components[i] = color.getComponents().get(i);
|
components[i] = color.getComponents().get(i);
|
||||||
}
|
}
|
||||||
String space = color.getColorSpace();
|
String space = color.getColorSpace();
|
||||||
log.trace(
|
|
||||||
"[ColorApply] Requested color space={} components={} nonStroking={}",
|
|
||||||
space,
|
|
||||||
Arrays.toString(components),
|
|
||||||
nonStroking);
|
|
||||||
if (space == null) {
|
if (space == null) {
|
||||||
// Infer color space from component count
|
// Infer color space from component count
|
||||||
PDColorSpace colorSpace;
|
PDColorSpace colorSpace;
|
||||||
@ -3082,43 +3076,6 @@ public class PdfJsonConversionService {
|
|||||||
return loadFallbackPdfFont(document);
|
return loadFallbackPdfFont(document);
|
||||||
}
|
}
|
||||||
|
|
||||||
// IMPORTANT: Dictionary restoration is disabled because deserialized dictionaries
|
|
||||||
// don't properly include the font stream references (FontFile/FontFile2/FontFile3).
|
|
||||||
// This results in fonts that structurally exist but can't encode glyphs, causing
|
|
||||||
// fallback to NotoSans. Instead, we ALWAYS use program bytes for reliable encoding.
|
|
||||||
// The cosDictionary field is preserved in the JSON for potential future use, but
|
|
||||||
// for now we rely on direct font program loading.
|
|
||||||
if (false && fontModel.getCosDictionary() != null) {
|
|
||||||
// Dictionary restoration code kept for reference but disabled
|
|
||||||
COSBase restored = deserializeCosValue(fontModel.getCosDictionary(), document);
|
|
||||||
if (restored instanceof COSDictionary cosDictionary) {
|
|
||||||
try {
|
|
||||||
PDFont font = PDFontFactory.createFont(cosDictionary);
|
|
||||||
if (font != null && font.isEmbedded()) {
|
|
||||||
// Verify font can actually encode a basic character
|
|
||||||
try {
|
|
||||||
font.encode("A");
|
|
||||||
applyAdditionalFontMetadata(document, font, fontModel);
|
|
||||||
log.debug(
|
|
||||||
"Successfully restored embedded font {} from dictionary",
|
|
||||||
fontModel.getId());
|
|
||||||
return font;
|
|
||||||
} catch (IOException | IllegalArgumentException encodingEx) {
|
|
||||||
log.warn(
|
|
||||||
"Font {} restored from dictionary but failed encoding test: {}; falling back to program bytes",
|
|
||||||
fontModel.getId(),
|
|
||||||
encodingEx.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (IOException ex) {
|
|
||||||
log.warn(
|
|
||||||
"Failed to restore font {} from stored dictionary: {}; falling back to program bytes",
|
|
||||||
fontModel.getId(),
|
|
||||||
ex.getMessage());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
String originalFormat =
|
String originalFormat =
|
||||||
fontModel.getProgramFormat() != null
|
fontModel.getProgramFormat() != null
|
||||||
? fontModel.getProgramFormat().toLowerCase(Locale.ROOT)
|
? fontModel.getProgramFormat().toLowerCase(Locale.ROOT)
|
||||||
@ -3263,6 +3220,34 @@ public class PdfJsonConversionService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// As a last resort, rebuild the original font dictionary which still references the
|
||||||
|
// embedded program streams captured during extraction. This handles subset fonts whose
|
||||||
|
// raw program bytes cannot be reloaded directly (e.g., missing Unicode cmap tables).
|
||||||
|
if (fontModel.getCosDictionary() != null) {
|
||||||
|
COSBase restored = deserializeCosValue(fontModel.getCosDictionary(), document);
|
||||||
|
if (restored instanceof COSDictionary cosDictionary) {
|
||||||
|
try {
|
||||||
|
PDFont font = PDFontFactory.createFont(cosDictionary);
|
||||||
|
if (font != null && font.isEmbedded()) {
|
||||||
|
applyAdditionalFontMetadata(document, font, fontModel);
|
||||||
|
log.debug(
|
||||||
|
"Successfully restored embedded font {} from original dictionary",
|
||||||
|
fontModel.getId());
|
||||||
|
return font;
|
||||||
|
}
|
||||||
|
log.debug(
|
||||||
|
"Restored font {} from dictionary but font was {}embedded; continuing",
|
||||||
|
fontModel.getId(),
|
||||||
|
font != null && font.isEmbedded() ? "" : "not ");
|
||||||
|
} catch (IOException ex) {
|
||||||
|
log.debug(
|
||||||
|
"Failed to restore font {} from stored dictionary: {}",
|
||||||
|
fontModel.getId(),
|
||||||
|
ex.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
log.warn(
|
log.warn(
|
||||||
"Font {} has no usable program bytes (originalFormat: {}, hasWebProgram: {}, hasPdfProgram: {})",
|
"Font {} has no usable program bytes (originalFormat: {}, hasWebProgram: {}, hasPdfProgram: {})",
|
||||||
fontModel.getId(),
|
fontModel.getId(),
|
||||||
@ -3888,15 +3873,6 @@ public class PdfJsonConversionService {
|
|||||||
element.setStrokeColor(toTextColor(graphicsState.getStrokingColor()));
|
element.setStrokeColor(toTextColor(graphicsState.getStrokingColor()));
|
||||||
}
|
}
|
||||||
element.setZOrder(1_000_000 + pageElements.size());
|
element.setZOrder(1_000_000 + pageElements.size());
|
||||||
if (log.isTraceEnabled()) {
|
|
||||||
log.trace(
|
|
||||||
"[TextCapture] text='{}' font={} size={} fill={} stroke={}",
|
|
||||||
sanitizeForLog(element.getText()),
|
|
||||||
fontId,
|
|
||||||
element.getFontSizeInPt(),
|
|
||||||
describeColor(element.getFillColor()),
|
|
||||||
describeColor(element.getStrokeColor()));
|
|
||||||
}
|
|
||||||
pageElements.add(element);
|
pageElements.add(element);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -3953,10 +3929,6 @@ public class PdfJsonConversionService {
|
|||||||
}
|
}
|
||||||
float[] components = color.getComponents();
|
float[] components = color.getComponents();
|
||||||
String colorSpaceName = colorSpace.getName();
|
String colorSpaceName = colorSpace.getName();
|
||||||
log.trace(
|
|
||||||
"[ColorCapture] Raw color space={} components={}",
|
|
||||||
colorSpaceName,
|
|
||||||
Arrays.toString(components));
|
|
||||||
float[] effective = components;
|
float[] effective = components;
|
||||||
try {
|
try {
|
||||||
float[] rgb = colorSpace.toRGB(components);
|
float[] rgb = colorSpace.toRGB(components);
|
||||||
@ -3974,7 +3946,6 @@ public class PdfJsonConversionService {
|
|||||||
for (float component : effective) {
|
for (float component : effective) {
|
||||||
values.add(component);
|
values.add(component);
|
||||||
}
|
}
|
||||||
log.trace("[ColorCapture] Stored color space={} components={}", colorSpaceName, values);
|
|
||||||
return PdfJsonTextColor.builder().colorSpace(colorSpaceName).components(values).build();
|
return PdfJsonTextColor.builder().colorSpace(colorSpaceName).components(values).build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user