Support CMap-data with only strings, when parsing TrueType composite fonts (bug 920426)
In the referenced bug, the embedded fonts contain custom CMap-data that only include strings. Note how for embedded composite TrueType fonts we're using the CMap-data when building the glyph mapping, and currently we end up with a completely empty map because the code expects only CID *numbers*. Furthermore, just fixing the glyph mapping alone isn't sufficient to fully address the bug, since we also need to consider this "special" kind of CMap-data when looking up glyph widths.
This commit is contained in:
		
							parent
							
								
									db7c91e7b1
								
							
						
					
					
						commit
						d3ca28bc34
					
				@ -401,6 +401,21 @@ function buildToFontChar(encoding, glyphsUnicodeMap, differences) {
 | 
				
			|||||||
  return toFontChar;
 | 
					  return toFontChar;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function convertCidString(charCode, cid, shouldThrow = false) {
 | 
				
			||||||
 | 
					  switch (cid.length) {
 | 
				
			||||||
 | 
					    case 1:
 | 
				
			||||||
 | 
					      return cid.charCodeAt(0);
 | 
				
			||||||
 | 
					    case 2:
 | 
				
			||||||
 | 
					      return (cid.charCodeAt(0) << 8) | cid.charCodeAt(1);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  const msg = `Unsupported CID string (charCode ${charCode}): "${cid}".`;
 | 
				
			||||||
 | 
					  if (shouldThrow) {
 | 
				
			||||||
 | 
					    throw new FormatError(msg);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  warn(msg);
 | 
				
			||||||
 | 
					  return cid;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * Rebuilds the char code to glyph ID map by moving all char codes to the
 | 
					 * Rebuilds the char code to glyph ID map by moving all char codes to the
 | 
				
			||||||
 * private use area. This is done to avoid issues with various problematic
 | 
					 * private use area. This is done to avoid issues with various problematic
 | 
				
			||||||
@ -929,7 +944,7 @@ class Font {
 | 
				
			|||||||
      return;
 | 
					      return;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    this.cidEncoding = properties.cidEncoding;
 | 
					    this.cidEncoding = properties.cidEncoding || "";
 | 
				
			||||||
    this.vertical = !!properties.vertical;
 | 
					    this.vertical = !!properties.vertical;
 | 
				
			||||||
    if (this.vertical) {
 | 
					    if (this.vertical) {
 | 
				
			||||||
      this.vmetrics = properties.vmetrics;
 | 
					      this.vmetrics = properties.vmetrics;
 | 
				
			||||||
@ -2612,6 +2627,9 @@ class Font {
 | 
				
			|||||||
      const isCidToGidMapEmpty = cidToGidMap.length === 0;
 | 
					      const isCidToGidMapEmpty = cidToGidMap.length === 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      properties.cMap.forEach(function (charCode, cid) {
 | 
					      properties.cMap.forEach(function (charCode, cid) {
 | 
				
			||||||
 | 
					        if (typeof cid === "string") {
 | 
				
			||||||
 | 
					          cid = convertCidString(charCode, cid, /* shouldThrow = */ true);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
        if (cid > 0xffff) {
 | 
					        if (cid > 0xffff) {
 | 
				
			||||||
          throw new FormatError("Max size of CID is 65,535");
 | 
					          throw new FormatError("Max size of CID is 65,535");
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
@ -3057,6 +3075,10 @@ class Font {
 | 
				
			|||||||
      let charcode = 0;
 | 
					      let charcode = 0;
 | 
				
			||||||
      if (this.composite && this.cMap.contains(glyphUnicode)) {
 | 
					      if (this.composite && this.cMap.contains(glyphUnicode)) {
 | 
				
			||||||
        charcode = this.cMap.lookup(glyphUnicode);
 | 
					        charcode = this.cMap.lookup(glyphUnicode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if (typeof charcode === "string") {
 | 
				
			||||||
 | 
					          charcode = convertCidString(glyphUnicode, charcode);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
      // ... via toUnicode map
 | 
					      // ... via toUnicode map
 | 
				
			||||||
      if (!charcode && this.toUnicode) {
 | 
					      if (!charcode && this.toUnicode) {
 | 
				
			||||||
@ -3085,6 +3107,10 @@ class Font {
 | 
				
			|||||||
    let widthCode = charcode;
 | 
					    let widthCode = charcode;
 | 
				
			||||||
    if (this.cMap && this.cMap.contains(charcode)) {
 | 
					    if (this.cMap && this.cMap.contains(charcode)) {
 | 
				
			||||||
      widthCode = this.cMap.lookup(charcode);
 | 
					      widthCode = this.cMap.lookup(charcode);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (typeof widthCode === "string") {
 | 
				
			||||||
 | 
					        widthCode = convertCidString(charcode, widthCode);
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    width = this.widths[widthCode];
 | 
					    width = this.widths[widthCode];
 | 
				
			||||||
    width = isNum(width) ? width : this.defaultWidth;
 | 
					    width = isNum(width) ? width : this.defaultWidth;
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										1
									
								
								test/pdfs/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								test/pdfs/.gitignore
									
									
									
									
										vendored
									
									
								
							@ -238,6 +238,7 @@
 | 
				
			|||||||
!bug900822.pdf
 | 
					!bug900822.pdf
 | 
				
			||||||
!bug1392647.pdf
 | 
					!bug1392647.pdf
 | 
				
			||||||
!issue918.pdf
 | 
					!issue918.pdf
 | 
				
			||||||
 | 
					!bug920426.pdf
 | 
				
			||||||
!issue1905.pdf
 | 
					!issue1905.pdf
 | 
				
			||||||
!issue2833.pdf
 | 
					!issue2833.pdf
 | 
				
			||||||
!issue2931.pdf
 | 
					!issue2931.pdf
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								test/pdfs/bug920426.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								test/pdfs/bug920426.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							@ -154,6 +154,12 @@
 | 
				
			|||||||
       "link": false,
 | 
					       "link": false,
 | 
				
			||||||
       "type": "eq"
 | 
					       "type": "eq"
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    {  "id": "bug920426",
 | 
				
			||||||
 | 
					       "file": "pdfs/bug920426.pdf",
 | 
				
			||||||
 | 
					       "md5": "2fd118b44513afb22509c3584388cc29",
 | 
				
			||||||
 | 
					       "rounds": 1,
 | 
				
			||||||
 | 
					       "type": "eq"
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    {  "id": "issue13343",
 | 
					    {  "id": "issue13343",
 | 
				
			||||||
       "file": "pdfs/issue13343.pdf",
 | 
					       "file": "pdfs/issue13343.pdf",
 | 
				
			||||||
       "md5": "f8bf1888839e15254555092c504e1900",
 | 
					       "md5": "f8bf1888839e15254555092c504e1900",
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user