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 = |
135 reinterpret_cast<uint16_t*>(const_cast<void*>((text))); | 135 reinterpret_cast<uint16_t*>(const_cast<void*>((text))); |
136 | 136 |
137 int maxGlyphID = max_glyphid_for_typeface(paint.getTypeface()); | 137 int maxGlyphID = max_glyphid_for_typeface(paint.getTypeface()); |
138 int validated; | 138 int validated; |
139 for (validated = 0; validated < numGlyphs; ++validated) { | 139 for (validated = 0; validated < numGlyphs; ++validated) { |
140 if (input[validated] > maxGlyphID) { | 140 if (input[validated] > maxGlyphID) { |
141 break; | 141 break; |
142 } | 142 } |
143 } | 143 } |
144 if (validated >= numGlyphs) { | 144 if (validated >= numGlyphs) { |
145 *glyphIDs = reinterpret_cast<uint16_t*>(const_cast<void*>((text))); | 145 *glyphIDs = reinterpret_cast<const uint16_t*>(text); |
mtklein
2014/10/02 21:10:11
this can be a static_cast<const uint16_t*>, right?
bungeman-skia
2014/10/02 22:28:17
Done. Here and above.
| |
146 return numGlyphs; | 146 return numGlyphs; |
147 } | 147 } |
148 | 148 |
149 // Silently drop anything out of range. | 149 // Silently drop anything out of range. |
150 storage->reset(numGlyphs); | 150 storage->reset(numGlyphs); |
151 if (validated > 0) { | 151 if (validated > 0) { |
152 memcpy(storage->get(), input, validated * sizeof(uint16_t)); | 152 memcpy(storage->get(), input, validated * sizeof(uint16_t)); |
153 } | 153 } |
154 | 154 |
155 for (int i = validated; i < numGlyphs; ++i) { | 155 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). | 1108 // making text unreadable (e.g. same text twice when using CSS shadows). |
1109 return; | 1109 return; |
1110 } | 1110 } |
1111 SkPaint textPaint = calculate_text_paint(paint); | 1111 SkPaint textPaint = calculate_text_paint(paint); |
1112 ScopedContentEntry content(this, d, textPaint, true); | 1112 ScopedContentEntry content(this, d, textPaint, true); |
1113 if (!content.entry()) { | 1113 if (!content.entry()) { |
1114 return; | 1114 return; |
1115 } | 1115 } |
1116 | 1116 |
1117 SkGlyphStorage storage(0); | 1117 SkGlyphStorage storage(0); |
1118 uint16_t* glyphIDs = NULL; | 1118 const uint16_t* glyphIDs = NULL; |
1119 int numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphIDs); | 1119 int numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphIDs); |
1120 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); | 1120 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
1121 | 1121 |
1122 SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); | 1122 SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); |
1123 align_text(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y); | 1123 align_text(glyphCacheProc, textPaint, glyphIDs, numGlyphs, &x, &y); |
1124 content.entry()->fContent.writeText("BT\n"); | 1124 content.entry()->fContent.writeText("BT\n"); |
1125 set_text_transform(x, y, textPaint.getTextSkewX(), | 1125 set_text_transform(x, y, textPaint.getTextSkewX(), |
1126 &content.entry()->fContent); | 1126 &content.entry()->fContent); |
1127 int consumedGlyphCount = 0; | 1127 int consumedGlyphCount = 0; |
1128 while (numGlyphs > consumedGlyphCount) { | 1128 while (numGlyphs > consumedGlyphCount) { |
1129 updateFont(textPaint, glyphIDs[consumedGlyphCount], content.entry()); | 1129 updateFont(textPaint, glyphIDs[consumedGlyphCount], content.entry()); |
1130 SkPDFFont* font = content.entry()->fState.fFont; | 1130 SkPDFFont* font = content.entry()->fState.fFont; |
1131 //TODO: the const_cast here is a bug if the encoding started out as glyp h encoding. | |
mtklein
2014/10/02 21:10:11
Can we assert it wasn't, or is this really happeni
bungeman-skia
2014/10/02 22:28:16
This will still 'work' here, but will mutate the '
mtklein
2014/10/03 13:48:58
Bloody hell.
| |
1131 int availableGlyphs = | 1132 int availableGlyphs = |
1132 font->glyphsToPDFFontEncoding(glyphIDs + consumedGlyphCount, | 1133 font->glyphsToPDFFontEncoding(const_cast<uint16_t*>(glyphIDs) + cons umedGlyphCount, |
1133 numGlyphs - consumedGlyphCount); | 1134 numGlyphs - consumedGlyphCount); |
1134 fFontGlyphUsage->noteGlyphUsage(font, glyphIDs + consumedGlyphCount, | 1135 fFontGlyphUsage->noteGlyphUsage(font, glyphIDs + consumedGlyphCount, |
1135 availableGlyphs); | 1136 availableGlyphs); |
1136 SkString encodedString = | 1137 SkString encodedString = |
1137 SkPDFString::FormatString(glyphIDs + consumedGlyphCount, | 1138 SkPDFString::FormatString(glyphIDs + consumedGlyphCount, |
1138 availableGlyphs, font->multiByteGlyphs()); | 1139 availableGlyphs, font->multiByteGlyphs()); |
1139 content.entry()->fContent.writeText(encodedString.c_str()); | 1140 content.entry()->fContent.writeText(encodedString.c_str()); |
1140 consumedGlyphCount += availableGlyphs; | 1141 consumedGlyphCount += availableGlyphs; |
1141 content.entry()->fContent.writeText(" Tj\n"); | 1142 content.entry()->fContent.writeText(" Tj\n"); |
1142 } | 1143 } |
(...skipping 10 matching lines...) Expand all Loading... | |
1153 return; | 1154 return; |
1154 } | 1155 } |
1155 SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos); | 1156 SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos); |
1156 SkPaint textPaint = calculate_text_paint(paint); | 1157 SkPaint textPaint = calculate_text_paint(paint); |
1157 ScopedContentEntry content(this, d, textPaint, true); | 1158 ScopedContentEntry content(this, d, textPaint, true); |
1158 if (!content.entry()) { | 1159 if (!content.entry()) { |
1159 return; | 1160 return; |
1160 } | 1161 } |
1161 | 1162 |
1162 SkGlyphStorage storage(0); | 1163 SkGlyphStorage storage(0); |
1163 uint16_t* glyphIDs = NULL; | 1164 const uint16_t* glyphIDs = NULL; |
1164 size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage, | 1165 size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage, &glyphID s); |
1165 &glyphIDs); | |
1166 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); | 1166 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); |
1167 | 1167 |
1168 SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); | 1168 SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); |
1169 content.entry()->fContent.writeText("BT\n"); | 1169 content.entry()->fContent.writeText("BT\n"); |
1170 updateFont(textPaint, glyphIDs[0], content.entry()); | 1170 updateFont(textPaint, glyphIDs[0], content.entry()); |
1171 for (size_t i = 0; i < numGlyphs; i++) { | 1171 for (size_t i = 0; i < numGlyphs; i++) { |
1172 SkPDFFont* font = content.entry()->fState.fFont; | 1172 SkPDFFont* font = content.entry()->fState.fFont; |
1173 uint16_t encodedValue = glyphIDs[i]; | 1173 uint16_t encodedValue = glyphIDs[i]; |
1174 if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) { | 1174 if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) { |
1175 // The current pdf font cannot encode the current glyph. | |
1176 // Try to get a pdf font which can encode the current glyph. | |
1175 updateFont(textPaint, glyphIDs[i], content.entry()); | 1177 updateFont(textPaint, glyphIDs[i], content.entry()); |
1176 i--; | 1178 font = content.entry()->fState.fFont; |
1177 continue; | 1179 if (font->glyphsToPDFFontEncoding(&encodedValue, 1) != 1) { |
1180 SkDEBUGFAIL("PDF could not encode glyph."); | |
1181 continue; | |
1182 } | |
1178 } | 1183 } |
1184 | |
1179 fFontGlyphUsage->noteGlyphUsage(font, &encodedValue, 1); | 1185 fFontGlyphUsage->noteGlyphUsage(font, &encodedValue, 1); |
1180 SkScalar x = offset.x() + pos[i * scalarsPerPos]; | 1186 SkScalar x = offset.x() + pos[i * scalarsPerPos]; |
1181 SkScalar y = offset.y() + (2 == scalarsPerPos ? pos[i * scalarsPerPos + 1] : 0); | 1187 SkScalar y = offset.y() + (2 == scalarsPerPos ? pos[i * scalarsPerPos + 1] : 0); |
1182 | 1188 |
1183 align_text(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y); | 1189 align_text(glyphCacheProc, textPaint, glyphIDs + i, 1, &x, &y); |
1184 set_text_transform(x, y, textPaint.getTextSkewX(), | 1190 set_text_transform(x, y, textPaint.getTextSkewX(), &content.entry()->fCo ntent); |
1185 &content.entry()->fContent); | |
1186 SkString encodedString = | 1191 SkString encodedString = |
1187 SkPDFString::FormatString(&encodedValue, 1, | 1192 SkPDFString::FormatString(&encodedValue, 1, font->multiByteGlyphs()) ; |
1188 font->multiByteGlyphs()); | |
1189 content.entry()->fContent.writeText(encodedString.c_str()); | 1193 content.entry()->fContent.writeText(encodedString.c_str()); |
1190 content.entry()->fContent.writeText(" Tj\n"); | 1194 content.entry()->fContent.writeText(" Tj\n"); |
1191 } | 1195 } |
1192 content.entry()->fContent.writeText("ET\n"); | 1196 content.entry()->fContent.writeText("ET\n"); |
1193 } | 1197 } |
1194 | 1198 |
1195 void SkPDFDevice::drawTextOnPath(const SkDraw& d, const void* text, size_t len, | 1199 void SkPDFDevice::drawTextOnPath(const SkDraw& d, const void* text, size_t len, |
1196 const SkPath& path, const SkMatrix* matrix, | 1200 const SkPath& path, const SkMatrix* matrix, |
1197 const SkPaint& paint) { | 1201 const SkPaint& paint) { |
1198 if (d.fClip->isEmpty()) { | 1202 if (d.fClip->isEmpty()) { |
(...skipping 987 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2186 SkAutoTUnref<SkPDFObject> image( | 2190 SkAutoTUnref<SkPDFObject> image( |
2187 SkPDFCreateImageObject(*bitmap, subset, fEncoder)); | 2191 SkPDFCreateImageObject(*bitmap, subset, fEncoder)); |
2188 if (!image) { | 2192 if (!image) { |
2189 return; | 2193 return; |
2190 } | 2194 } |
2191 | 2195 |
2192 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()), | 2196 SkPDFUtils::DrawFormXObject(this->addXObjectResource(image.get()), |
2193 &content.entry()->fContent); | 2197 &content.entry()->fContent); |
2194 } | 2198 } |
2195 | 2199 |
OLD | NEW |