OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkPDFDevice.h" | 8 #include "SkPDFDevice.h" |
9 | 9 |
10 #include "SkAnnotation.h" | 10 #include "SkAnnotation.h" |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 static int max_glyphid_for_typeface(SkTypeface* typeface) { | 111 static int max_glyphid_for_typeface(SkTypeface* typeface) { |
112 SkAutoResolveDefaultTypeface autoResolve(typeface); | 112 SkAutoResolveDefaultTypeface autoResolve(typeface); |
113 typeface = autoResolve.get(); | 113 typeface = autoResolve.get(); |
114 return typeface->countGlyphs() - 1; | 114 return typeface->countGlyphs() - 1; |
115 } | 115 } |
116 | 116 |
117 typedef SkAutoSTMalloc<128, uint16_t> SkGlyphStorage; | 117 typedef SkAutoSTMalloc<128, uint16_t> SkGlyphStorage; |
118 | 118 |
119 static int force_glyph_encoding(const SkPaint& paint, const void* text, | 119 static int force_glyph_encoding(const SkPaint& paint, const void* text, |
120 size_t len, SkGlyphStorage* storage, | 120 size_t len, SkGlyphStorage* storage, |
121 uint16_t** glyphIDs) { | 121 const uint16_t** glyphIDs) { |
122 // Make sure we have a glyph id encoding. | 122 // Make sure we have a glyph id encoding. |
123 if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) { | 123 if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) { |
124 int numGlyphs = paint.textToGlyphs(text, len, NULL); | 124 int numGlyphs = paint.textToGlyphs(text, len, NULL); |
125 storage->reset(numGlyphs); | 125 storage->reset(numGlyphs); |
126 paint.textToGlyphs(text, len, storage->get()); | 126 paint.textToGlyphs(text, len, storage->get()); |
127 *glyphIDs = storage->get(); | 127 *glyphIDs = storage->get(); |
128 return numGlyphs; | 128 return numGlyphs; |
129 } | 129 } |
130 | 130 |
131 // For user supplied glyph ids we need to validate them. | 131 // For user supplied glyph ids we need to validate them. |
132 SkASSERT((len & 1) == 0); | 132 SkASSERT((len & 1) == 0); |
133 int numGlyphs = SkToInt(len / 2); | 133 int numGlyphs = SkToInt(len / 2); |
134 const uint16_t* input = | 134 const uint16_t* input = static_cast<const uint16_t*>(text); |
135 reinterpret_cast<uint16_t*>(const_cast<void*>((text))); | |
136 | 135 |
137 int maxGlyphID = max_glyphid_for_typeface(paint.getTypeface()); | 136 int maxGlyphID = max_glyphid_for_typeface(paint.getTypeface()); |
138 int validated; | 137 int validated; |
139 for (validated = 0; validated < numGlyphs; ++validated) { | 138 for (validated = 0; validated < numGlyphs; ++validated) { |
140 if (input[validated] > maxGlyphID) { | 139 if (input[validated] > maxGlyphID) { |
141 break; | 140 break; |
142 } | 141 } |
143 } | 142 } |
144 if (validated >= numGlyphs) { | 143 if (validated >= numGlyphs) { |
145 *glyphIDs = reinterpret_cast<uint16_t*>(const_cast<void*>((text))); | 144 *glyphIDs = static_cast<const uint16_t*>(text); |
146 return numGlyphs; | 145 return numGlyphs; |
147 } | 146 } |
148 | 147 |
149 // Silently drop anything out of range. | 148 // Silently drop anything out of range. |
150 storage->reset(numGlyphs); | 149 storage->reset(numGlyphs); |
151 if (validated > 0) { | 150 if (validated > 0) { |
152 memcpy(storage->get(), input, validated * sizeof(uint16_t)); | 151 memcpy(storage->get(), input, validated * sizeof(uint16_t)); |
153 } | 152 } |
154 | 153 |
155 for (int i = validated; i < numGlyphs; ++i) { | 154 for (int i = validated; i < numGlyphs; ++i) { |
(...skipping 952 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1108 // making text unreadable (e.g. same text twice when using CSS shadows). | 1107 // making text unreadable (e.g. same text twice when using CSS shadows). |
1109 return; | 1108 return; |
1110 } | 1109 } |
1111 SkPaint textPaint = calculate_text_paint(paint); | 1110 SkPaint textPaint = calculate_text_paint(paint); |
1112 ScopedContentEntry content(this, d, textPaint, true); | 1111 ScopedContentEntry content(this, d, textPaint, true); |
1113 if (!content.entry()) { | 1112 if (!content.entry()) { |
1114 return; | 1113 return; |
1115 } | 1114 } |
1116 | 1115 |
1117 SkGlyphStorage storage(0); | 1116 SkGlyphStorage storage(0); |
1118 uint16_t* glyphIDs = NULL; | 1117 const uint16_t* glyphIDs = NULL; |
1119 int numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphIDs); | 1118 int numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphIDs); |
1120 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); | 1119 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
1121 | 1120 |
1122 SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); | 1121 SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); |
1123 align_text(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y); | 1122 align_text(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y); |
1124 content.entry()->fContent.writeText("BT\n"); | 1123 content.entry()->fContent.writeText("BT\n"); |
1125 set_text_transform(x, y, textPaint.getTextSkewX(), | 1124 set_text_transform(x, y, textPaint.getTextSkewX(), |
1126 &content.entry()->fContent); | 1125 &content.entry()->fContent); |
1127 int consumedGlyphCount = 0; | 1126 int consumedGlyphCount = 0; |
1128 while (numGlyphs > consumedGlyphCount) { | 1127 while (numGlyphs > consumedGlyphCount) { |
1129 updateFont(textPaint, glyphIDs[consumedGlyphCount], content.entry()); | 1128 updateFont(textPaint, glyphIDs[consumedGlyphCount], content.entry()); |
1130 SkPDFFont* font = content.entry()->fState.fFont; | 1129 SkPDFFont* font = content.entry()->fState.fFont; |
| 1130 //TODO: the const_cast here is a bug if the encoding started out as glyp
h encoding. |
1131 int availableGlyphs = | 1131 int availableGlyphs = |
1132 font->glyphsToPDFFontEncoding(glyphIDs + consumedGlyphCount, | 1132 font->glyphsToPDFFontEncoding(const_cast<uint16_t*>(glyphIDs) + cons
umedGlyphCount, |
1133 numGlyphs - consumedGlyphCount); | 1133 numGlyphs - consumedGlyphCount); |
1134 fFontGlyphUsage->noteGlyphUsage(font, glyphIDs + consumedGlyphCount, | 1134 fFontGlyphUsage->noteGlyphUsage(font, glyphIDs + consumedGlyphCount, |
1135 availableGlyphs); | 1135 availableGlyphs); |
1136 SkString encodedString = | 1136 SkString encodedString = |
1137 SkPDFString::FormatString(glyphIDs + consumedGlyphCount, | 1137 SkPDFString::FormatString(glyphIDs + consumedGlyphCount, |
1138 availableGlyphs, font->multiByteGlyphs()); | 1138 availableGlyphs, font->multiByteGlyphs()); |
1139 content.entry()->fContent.writeText(encodedString.c_str()); | 1139 content.entry()->fContent.writeText(encodedString.c_str()); |
1140 consumedGlyphCount += availableGlyphs; | 1140 consumedGlyphCount += availableGlyphs; |
1141 content.entry()->fContent.writeText(" Tj\n"); | 1141 content.entry()->fContent.writeText(" Tj\n"); |
1142 } | 1142 } |
(...skipping 10 matching lines...) Expand all Loading... |
1153 return; | 1153 return; |
1154 } | 1154 } |
1155 SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos); | 1155 SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos); |
1156 SkPaint textPaint = calculate_text_paint(paint); | 1156 SkPaint textPaint = calculate_text_paint(paint); |
1157 ScopedContentEntry content(this, d, textPaint, true); | 1157 ScopedContentEntry content(this, d, textPaint, true); |
1158 if (!content.entry()) { | 1158 if (!content.entry()) { |
1159 return; | 1159 return; |
1160 } | 1160 } |
1161 | 1161 |
1162 SkGlyphStorage storage(0); | 1162 SkGlyphStorage storage(0); |
1163 uint16_t* glyphIDs = NULL; | 1163 const uint16_t* glyphIDs = NULL; |
1164 size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage, | 1164 size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphID
s); |
1165 &glyphIDs); | |
1166 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); | 1165 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
1167 | 1166 |
1168 SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); | 1167 SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); |
1169 content.entry()->fContent.writeText("BT\n"); | 1168 content.entry()->fContent.writeText("BT\n"); |
1170 updateFont(textPaint, glyphIDs[0], content.entry()); | 1169 updateFont(textPaint, glyphIDs[0], content.entry()); |
1171 for (size_t i = 0; i < numGlyphs; i++) { | 1170 for (size_t i = 0; i < numGlyphs; i++) { |
1172 SkPDFFont* font = content.entry()->fState.fFont; | 1171 SkPDFFont* font = content.entry()->fState.fFont; |
1173 uint16_t encodedValue = glyphIDs[i]; | 1172 uint16_t encodedValue = glyphIDs[i]; |
1174 if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) { | 1173 if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) { |
| 1174 // The current pdf font cannot encode the current glyph. |
| 1175 // Try to get a pdf font which can encode the current glyph. |
1175 updateFont(textPaint, glyphIDs[i], content.entry()); | 1176 updateFont(textPaint, glyphIDs[i], content.entry()); |
1176 i--; | 1177 font = content.entry()->fState.fFont; |
1177 continue; | 1178 if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) { |
| 1179 SkDEBUGFAIL("PDF could not encode glyph."); |
| 1180 continue; |
| 1181 } |
1178 } | 1182 } |
| 1183 |
1179 fFontGlyphUsage->noteGlyphUsage(font, &encodedValue, 1); | 1184 fFontGlyphUsage->noteGlyphUsage(font, &encodedValue, 1); |
1180 SkScalar x = offset.x() + pos[i * scalarsPerPos]; | 1185 SkScalar x = offset.x() + pos[i * scalarsPerPos]; |
1181 SkScalar y = offset.y() + (2 == scalarsPerPos ? pos[i * scalarsPerPos +
1] : 0); | 1186 SkScalar y = offset.y() + (2 == scalarsPerPos ? pos[i * scalarsPerPos +
1] : 0); |
1182 | 1187 |
1183 align_text(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y); | 1188 align_text(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y); |
1184 set_text_transform(x, y, textPaint.getTextSkewX(), | 1189 set_text_transform(x, y, textPaint.getTextSkewX(), &content.entry()->fCo
ntent); |
1185 &content.entry()->fContent); | |
1186 SkString encodedString = | 1190 SkString encodedString = |
1187 SkPDFString::FormatString(&encodedValue, 1, | 1191 SkPDFString::FormatString(&encodedValue, 1, font->multiByteGlyphs())
; |
1188 font->multiByteGlyphs()); | |
1189 content.entry()->fContent.writeText(encodedString.c_str()); | 1192 content.entry()->fContent.writeText(encodedString.c_str()); |
1190 content.entry()->fContent.writeText(" Tj\n"); | 1193 content.entry()->fContent.writeText(" Tj\n"); |
1191 } | 1194 } |
1192 content.entry()->fContent.writeText("ET\n"); | 1195 content.entry()->fContent.writeText("ET\n"); |
1193 } | 1196 } |
1194 | 1197 |
1195 void SkPDFDevice::drawTextOnPath(const SkDraw& d, const void* text, size_t len, | 1198 void SkPDFDevice::drawTextOnPath(const SkDraw& d, const void* text, size_t len, |
1196 const SkPath& path, const SkMatrix* matrix, | 1199 const SkPath& path, const SkMatrix* matrix, |
1197 const SkPaint& paint) { | 1200 const SkPaint& paint) { |
1198 if (d.fClip->isEmpty()) { | 1201 if (d.fClip->isEmpty()) { |
(...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2186 SkAutoTUnref<SkPDFObject> image( | 2189 SkAutoTUnref<SkPDFObject> image( |
2187 SkPDFCreateImageObject(*bitmap, subset, fEncoder)); | 2190 SkPDFCreateImageObject(*bitmap, subset, fEncoder)); |
2188 if (!image) { | 2191 if (!image) { |
2189 return; | 2192 return; |
2190 } | 2193 } |
2191 | 2194 |
2192 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()), | 2195 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()), |
2193 &content.entry()->fContent); | 2196 &content.entry()->fContent); |
2194 } | 2197 } |
2195 | 2198 |
OLD | NEW |