Merge pull request #6588 from yurydelendik/spacing
Better spacing in text layer.
This commit is contained in:
		
						commit
						7e8dacf57b
					
				| @ -350,9 +350,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { | ||||
| 
 | ||||
|         for (var i = 0, ii = glyphs.length; i < ii; i++) { | ||||
|           var glyph = glyphs[i]; | ||||
|           if (glyph === null) { | ||||
|             continue; | ||||
|           } | ||||
|           buildPath(glyph.fontChar); | ||||
| 
 | ||||
|           // If the glyph has an accent we need to build a path for its
 | ||||
| @ -1012,10 +1009,6 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { | ||||
|         var defaultVMetrics = font.defaultVMetrics; | ||||
|         for (var i = 0; i < glyphs.length; i++) { | ||||
|           var glyph = glyphs[i]; | ||||
|           if (!glyph) { // Previous glyph was a space.
 | ||||
|             width += textState.wordSpacing * textState.textHScale; | ||||
|             continue; | ||||
|           } | ||||
|           var vMetricX = null; | ||||
|           var vMetricY = null; | ||||
|           var glyphWidth = null; | ||||
| @ -1051,11 +1044,14 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { | ||||
|           // var x = pt[0];
 | ||||
|           // var y = pt[1];
 | ||||
| 
 | ||||
|           var charSpacing = 0; | ||||
|           if (textChunk.str.length > 0) { | ||||
|             // Apply char spacing only when there are chars.
 | ||||
|             // As a result there is only spacing between glyphs.
 | ||||
|             charSpacing = textState.charSpacing; | ||||
|           var charSpacing = textState.charSpacing; | ||||
|           if (glyph.isSpace) { | ||||
|             var wordSpacing = textState.wordSpacing; | ||||
|             charSpacing += wordSpacing; | ||||
|             if (wordSpacing > 0) { | ||||
|               addFakeSpaces(wordSpacing * 1000 / textState.fontSize, | ||||
|                             textChunk.str); | ||||
|             } | ||||
|           } | ||||
| 
 | ||||
|           var tx = 0; | ||||
| @ -1089,6 +1085,22 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { | ||||
|         return textChunk; | ||||
|       } | ||||
| 
 | ||||
|       function addFakeSpaces(width, strBuf) { | ||||
|         var spaceWidth = textState.font.spaceWidth; | ||||
|         if (spaceWidth <= 0) { | ||||
|           return; | ||||
|         } | ||||
|         var fakeSpaces = width / spaceWidth; | ||||
|         if (fakeSpaces > MULTI_SPACE_FACTOR) { | ||||
|           fakeSpaces = Math.round(fakeSpaces); | ||||
|           while (fakeSpaces--) { | ||||
|             strBuf.push(' '); | ||||
|           } | ||||
|         } else if (fakeSpaces > SPACE_FACTOR) { | ||||
|           strBuf.push(' '); | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|       var timeSlotManager = new TimeSlotManager(); | ||||
| 
 | ||||
|       return new Promise(function next(resolve, reject) { | ||||
| @ -1167,29 +1179,26 @@ var PartialEvaluator = (function PartialEvaluatorClosure() { | ||||
|                   // In the default coordinate system, a positive adjustment
 | ||||
|                   // has the effect of moving the next glyph painted either to
 | ||||
|                   // the left or down by the given amount.
 | ||||
|                   var val = items[j] * textState.fontSize / 1000; | ||||
|                   var advance = items[j]; | ||||
|                   var val = advance * textState.fontSize / 1000; | ||||
|                   if (textState.font.vertical) { | ||||
|                     offset = val * textState.textMatrix[3]; | ||||
|                     textState.translateTextMatrix(0, offset); | ||||
|                     offset = val * | ||||
|                       (textState.textHScale * textState.textMatrix[2] + | ||||
|                        textState.textMatrix[3]); | ||||
|                     textState.translateTextMatrix(0, val); | ||||
|                     // Value needs to be added to height to paint down.
 | ||||
|                     textChunk.height += offset; | ||||
|                   } else { | ||||
|                     offset = val * textState.textHScale * | ||||
|                                    textState.textMatrix[0]; | ||||
|                     textState.translateTextMatrix(offset, 0); | ||||
|                     offset = val * ( | ||||
|                       textState.textHScale * textState.textMatrix[0] + | ||||
|                       textState.textMatrix[1]); | ||||
|                     textState.translateTextMatrix(-val, 0); | ||||
|                     // Value needs to be subtracted from width to paint left.
 | ||||
|                     textChunk.width -= offset; | ||||
|                     advance = -advance; | ||||
|                   } | ||||
|                   if (items[j] < 0 && textState.font.spaceWidth > 0) { | ||||
|                     var fakeSpaces = -items[j] / textState.font.spaceWidth; | ||||
|                     if (fakeSpaces > MULTI_SPACE_FACTOR) { | ||||
|                       fakeSpaces = Math.round(fakeSpaces); | ||||
|                       while (fakeSpaces--) { | ||||
|                         textChunk.str.push(' '); | ||||
|                       } | ||||
|                     } else if (fakeSpaces > SPACE_FACTOR) { | ||||
|                       textChunk.str.push(' '); | ||||
|                     } | ||||
|                   if (advance > 0) { | ||||
|                     addFakeSpaces(advance, textChunk.str); | ||||
|                   } | ||||
|                 } | ||||
|               } | ||||
|  | ||||
| @ -2170,23 +2170,26 @@ function getFontType(type, subtype) { | ||||
| } | ||||
| 
 | ||||
| var Glyph = (function GlyphClosure() { | ||||
|   function Glyph(fontChar, unicode, accent, width, vmetric, operatorListId) { | ||||
|   function Glyph(fontChar, unicode, accent, width, vmetric, operatorListId, | ||||
|                  isSpace) { | ||||
|     this.fontChar = fontChar; | ||||
|     this.unicode = unicode; | ||||
|     this.accent = accent; | ||||
|     this.width = width; | ||||
|     this.vmetric = vmetric; | ||||
|     this.operatorListId = operatorListId; | ||||
|     this.isSpace = isSpace; | ||||
|   } | ||||
| 
 | ||||
|   Glyph.prototype.matchesForCache = | ||||
|       function(fontChar, unicode, accent, width, vmetric, operatorListId) { | ||||
|   Glyph.prototype.matchesForCache = function(fontChar, unicode, accent, width, | ||||
|                                              vmetric, operatorListId, isSpace) { | ||||
|     return this.fontChar === fontChar && | ||||
|            this.unicode === unicode && | ||||
|            this.accent === accent && | ||||
|            this.width === width && | ||||
|            this.vmetric === vmetric && | ||||
|            this.operatorListId === operatorListId; | ||||
|            this.operatorListId === operatorListId && | ||||
|            this.isSpace === isSpace; | ||||
|   }; | ||||
| 
 | ||||
|   return Glyph; | ||||
| @ -4701,7 +4704,7 @@ var Font = (function FontClosure() { | ||||
|       return width; | ||||
|     }, | ||||
| 
 | ||||
|     charToGlyph: function Font_charToGlyph(charcode) { | ||||
|     charToGlyph: function Font_charToGlyph(charcode, isSpace) { | ||||
|       var fontCharCode, width, operatorListId; | ||||
| 
 | ||||
|       var widthCode = charcode; | ||||
| @ -4744,9 +4747,9 @@ var Font = (function FontClosure() { | ||||
|       var glyph = this.glyphCache[charcode]; | ||||
|       if (!glyph || | ||||
|           !glyph.matchesForCache(fontChar, unicode, accent, width, vmetric, | ||||
|                                  operatorListId)) { | ||||
|                                  operatorListId, isSpace)) { | ||||
|         glyph = new Glyph(fontChar, unicode, accent, width, vmetric, | ||||
|                           operatorListId); | ||||
|                           operatorListId, isSpace); | ||||
|         this.glyphCache[charcode] = glyph; | ||||
|       } | ||||
|       return glyph; | ||||
| @ -4782,22 +4785,16 @@ var Font = (function FontClosure() { | ||||
|           charcode = c.charcode; | ||||
|           var length = c.length; | ||||
|           i += length; | ||||
|           glyph = this.charToGlyph(charcode); | ||||
|           // Space is char with code 0x20 and length 1 in multiple-byte codes.
 | ||||
|           var isSpace = length === 1 && chars.charCodeAt(i - 1) === 0x20; | ||||
|           glyph = this.charToGlyph(charcode, isSpace); | ||||
|           glyphs.push(glyph); | ||||
|           // placing null after each word break charcode (ASCII SPACE)
 | ||||
|           // Ignore occurences of 0x20 in multiple-byte codes.
 | ||||
|           if (length === 1 && chars.charCodeAt(i - 1) === 0x20) { | ||||
|             glyphs.push(null); | ||||
|           } | ||||
|         } | ||||
|       } else { | ||||
|         for (i = 0, ii = chars.length; i < ii; ++i) { | ||||
|           charcode = chars.charCodeAt(i); | ||||
|           glyph = this.charToGlyph(charcode); | ||||
|           glyph = this.charToGlyph(charcode, charcode === 0x20); | ||||
|           glyphs.push(glyph); | ||||
|           if (charcode === 0x20) { | ||||
|             glyphs.push(null); | ||||
|           } | ||||
|         } | ||||
|       } | ||||
| 
 | ||||
|  | ||||
| @ -1397,16 +1397,13 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { | ||||
|       var x = 0, i; | ||||
|       for (i = 0; i < glyphsLength; ++i) { | ||||
|         var glyph = glyphs[i]; | ||||
|         if (glyph === null) { | ||||
|           // word break
 | ||||
|           x += fontDirection * wordSpacing; | ||||
|           continue; | ||||
|         } else if (isNum(glyph)) { | ||||
|         if (isNum(glyph)) { | ||||
|           x += spacingDir * glyph * fontSize / 1000; | ||||
|           continue; | ||||
|         } | ||||
| 
 | ||||
|         var restoreNeeded = false; | ||||
|         var spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing; | ||||
|         var character = glyph.fontChar; | ||||
|         var accent = glyph.accent; | ||||
|         var scaledX, scaledY, scaledAccentX, scaledAccentY; | ||||
| @ -1450,7 +1447,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { | ||||
|           } | ||||
|         } | ||||
| 
 | ||||
|         var charWidth = width * widthAdvanceScale + charSpacing * fontDirection; | ||||
|         var charWidth = width * widthAdvanceScale + spacing * fontDirection; | ||||
|         x += charWidth; | ||||
| 
 | ||||
|         if (restoreNeeded) { | ||||
| @ -1495,18 +1492,14 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { | ||||
| 
 | ||||
|       for (i = 0; i < glyphsLength; ++i) { | ||||
|         glyph = glyphs[i]; | ||||
|         if (glyph === null) { | ||||
|           // word break
 | ||||
|           this.ctx.translate(wordSpacing, 0); | ||||
|           current.x += wordSpacing * textHScale; | ||||
|           continue; | ||||
|         } else if (isNum(glyph)) { | ||||
|         if (isNum(glyph)) { | ||||
|           spacingLength = spacingDir * glyph * fontSize / 1000; | ||||
|           this.ctx.translate(spacingLength, 0); | ||||
|           current.x += spacingLength * textHScale; | ||||
|           continue; | ||||
|         } | ||||
| 
 | ||||
|         var spacing = (glyph.isSpace ? wordSpacing : 0) + charSpacing; | ||||
|         var operatorList = font.charProcOperatorList[glyph.operatorListId]; | ||||
|         if (!operatorList) { | ||||
|           warn('Type3 character \"' + glyph.operatorListId + | ||||
| @ -1521,7 +1514,7 @@ var CanvasGraphics = (function CanvasGraphicsClosure() { | ||||
|         this.restore(); | ||||
| 
 | ||||
|         var transformed = Util.applyTransform([glyph.width, 0], fontMatrix); | ||||
|         width = transformed[0] * fontSize + charSpacing; | ||||
|         width = transformed[0] * fontSize + spacing; | ||||
| 
 | ||||
|         ctx.translate(width, 0); | ||||
|         current.x += width * textHScale; | ||||
|  | ||||
							
								
								
									
										1
									
								
								test/pdfs/.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								test/pdfs/.gitignore
									
									
									
									
										vendored
									
									
								
							| @ -29,6 +29,7 @@ | ||||
| !issue3205r.pdf | ||||
| !issue3879r.pdf | ||||
| !close-path-bug.pdf | ||||
| !issue6019.pdf | ||||
| !issue1293r.pdf | ||||
| !issue6541.pdf | ||||
| !issue2948.pdf | ||||
|  | ||||
							
								
								
									
										80
									
								
								test/pdfs/issue6019.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								test/pdfs/issue6019.pdf
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,80 @@ | ||||
| %PDF-1.7 | ||||
| %âãÏÓ | ||||
| 1 0 obj  | ||||
| << | ||||
| /Type /Encoding | ||||
| /BaseEncoding /WinAnsiEncoding | ||||
| >> | ||||
| endobj  | ||||
| 2 0 obj  | ||||
| << | ||||
| /Pages 3 0 R | ||||
| /Type /Catalog | ||||
| >> | ||||
| endobj  | ||||
| 3 0 obj  | ||||
| << | ||||
| /Kids [4 0 R] | ||||
| /Count 1 | ||||
| /Type /Pages | ||||
| >> | ||||
| endobj  | ||||
| 4 0 obj  | ||||
| << | ||||
| /Rotate 90 | ||||
| /Parent 3 0 R | ||||
| /MediaBox [0 0 50 400] | ||||
| /Resources  | ||||
| << | ||||
| /Font  | ||||
| << | ||||
| /F1 5 0 R | ||||
| >> | ||||
| >> | ||||
| /Contents 6 0 R | ||||
| /Type /Page | ||||
| >> | ||||
| endobj  | ||||
| 5 0 obj  | ||||
| << | ||||
| /BaseFont /Times-Italic | ||||
| /Subtype /Type1 | ||||
| /Encoding 1 0 R | ||||
| /Type /Font | ||||
| >> | ||||
| endobj  | ||||
| 6 0 obj  | ||||
| << | ||||
| /Length 108 | ||||
| >> | ||||
| stream | ||||
| BT | ||||
| /F1 1 Tf | ||||
| 0 24 -24 0 30 30 Tm | ||||
| 0 Tw | ||||
| (Ð)Tj | ||||
| 0.94 0 TD | ||||
| -0.0002 Tc | ||||
| 0.0002 Tw | ||||
| [(Medicine Bow)-3653(  936)]TJ | ||||
| ET | ||||
| 
 | ||||
| endstream  | ||||
| endobj xref | ||||
| 0 7 | ||||
| 0000000000 65535 f  | ||||
| 0000000015 00000 n  | ||||
| 0000000085 00000 n  | ||||
| 0000000136 00000 n  | ||||
| 0000000195 00000 n  | ||||
| 0000000335 00000 n  | ||||
| 0000000426 00000 n  | ||||
| trailer | ||||
| 
 | ||||
| << | ||||
| /Root 2 0 R | ||||
| /Size 7 | ||||
| >> | ||||
| startxref | ||||
| 587 | ||||
| %%EOF | ||||
| @ -1288,6 +1288,13 @@ | ||||
|        "link": false, | ||||
|        "type": "eq" | ||||
|     }, | ||||
|     { | ||||
|       "id": "issue6019-text", | ||||
|       "file": "pdfs/issue6019.pdf", | ||||
|       "md5": "7a2e5dda3b0fc5c2e9060e378a8cdc4e", | ||||
|       "rounds": 1, | ||||
|       "type": "text" | ||||
|     }, | ||||
|     {  "id": "bug893730", | ||||
|        "file": "pdfs/bug893730.pdf", | ||||
|        "md5": "2587379fb1b3bbff89c14f0863e78383", | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user