| 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 |