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 1213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1224 SkASSERT(len <= 65535); | 1224 SkASSERT(len <= 65535); |
1225 SkString tmp(len); | 1225 SkString tmp(len); |
1226 for (size_t i = 0; i < len; i++) { | 1226 for (size_t i = 0; i < len; i++) { |
1227 SkASSERT(0 == input[i] >> 8); | 1227 SkASSERT(0 == input[i] >> 8); |
1228 tmp[i] = static_cast<uint8_t>(input[i]); | 1228 tmp[i] = static_cast<uint8_t>(input[i]); |
1229 } | 1229 } |
1230 return SkPDFUtils::FormatString(tmp.c_str(), tmp.size()); | 1230 return SkPDFUtils::FormatString(tmp.c_str(), tmp.size()); |
1231 } | 1231 } |
1232 } | 1232 } |
1233 | 1233 |
| 1234 static void draw_transparent_text(SkPDFDevice* device, |
| 1235 const SkDraw& d, |
| 1236 const void* text, size_t len, |
| 1237 SkScalar x, SkScalar y, |
| 1238 const SkPaint& srcPaint) { |
| 1239 |
| 1240 SkPaint transparent; |
| 1241 if (!SkPDFFont::CanEmbedTypeface(transparent.getTypeface(), |
| 1242 device->getCanon())) { |
| 1243 SkDEBUGFAIL("default typeface should be embeddable"); |
| 1244 return; // Avoid infinite loop in release. |
| 1245 } |
| 1246 transparent.setTextSize(srcPaint.getTextSize()); |
| 1247 transparent.setColor(SK_ColorTRANSPARENT); |
| 1248 switch (srcPaint.getTextEncoding()) { |
| 1249 case SkPaint::kGlyphID_TextEncoding: { |
| 1250 // Since a glyphId<->Unicode mapping is typeface-specific, |
| 1251 // map back to Unicode first. |
| 1252 size_t glyphCount = len / 2; |
| 1253 SkAutoTMalloc<SkUnichar> unichars(glyphCount); |
| 1254 srcPaint.glyphsToUnichars( |
| 1255 (const uint16_t*)text, SkToInt(glyphCount), &unichars[0]); |
| 1256 transparent.setTextEncoding(SkPaint::kUTF32_TextEncoding); |
| 1257 device->drawText(d, &unichars[0], |
| 1258 glyphCount * sizeof(SkUnichar), |
| 1259 x, y, transparent); |
| 1260 break; |
| 1261 } |
| 1262 case SkPaint::kUTF8_TextEncoding: |
| 1263 case SkPaint::kUTF16_TextEncoding: |
| 1264 case SkPaint::kUTF32_TextEncoding: |
| 1265 transparent.setTextEncoding(srcPaint.getTextEncoding()); |
| 1266 device->drawText(d, text, len, x, y, transparent); |
| 1267 break; |
| 1268 default: |
| 1269 SkFAIL("unknown text encoding"); |
| 1270 } |
| 1271 } |
| 1272 |
| 1273 |
1234 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, | 1274 void SkPDFDevice::drawText(const SkDraw& d, const void* text, size_t len, |
1235 SkScalar x, SkScalar y, const SkPaint& srcPaint) { | 1275 SkScalar x, SkScalar y, const SkPaint& srcPaint) { |
| 1276 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) { |
| 1277 // http://skbug.com/3866 |
| 1278 SkPath path; |
| 1279 srcPaint.getTextPath(text, len, x, y, &path); |
| 1280 this->drawPath(d, path, srcPaint, &SkMatrix::I(), true); |
| 1281 // Draw text transparently to make it copyable/searchable/accessable. |
| 1282 draw_transparent_text(this, d, text, len, x, y, srcPaint); |
| 1283 return; |
| 1284 } |
1236 SkPaint paint = srcPaint; | 1285 SkPaint paint = srcPaint; |
1237 replace_srcmode_on_opaque_paint(&paint); | 1286 replace_srcmode_on_opaque_paint(&paint); |
1238 | 1287 |
1239 NOT_IMPLEMENTED(paint.getMaskFilter() != nullptr, false); | 1288 NOT_IMPLEMENTED(paint.getMaskFilter() != nullptr, false); |
1240 if (paint.getMaskFilter() != nullptr) { | 1289 if (paint.getMaskFilter() != nullptr) { |
1241 // Don't pretend we support drawing MaskFilters, it makes for artifacts | 1290 // Don't pretend we support drawing MaskFilters, it makes for artifacts |
1242 // making text unreadable (e.g. same text twice when using CSS shadows). | 1291 // making text unreadable (e.g. same text twice when using CSS shadows). |
1243 return; | 1292 return; |
1244 } | 1293 } |
1245 SkPaint textPaint = calculate_text_paint(paint); | 1294 SkPaint textPaint = calculate_text_paint(paint); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1278 content.entry()->fContent.writeText(encodedString.c_str()); | 1327 content.entry()->fContent.writeText(encodedString.c_str()); |
1279 consumedGlyphCount += availableGlyphs; | 1328 consumedGlyphCount += availableGlyphs; |
1280 content.entry()->fContent.writeText(" Tj\n"); | 1329 content.entry()->fContent.writeText(" Tj\n"); |
1281 } | 1330 } |
1282 content.entry()->fContent.writeText("ET\n"); | 1331 content.entry()->fContent.writeText("ET\n"); |
1283 } | 1332 } |
1284 | 1333 |
1285 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len, | 1334 void SkPDFDevice::drawPosText(const SkDraw& d, const void* text, size_t len, |
1286 const SkScalar pos[], int scalarsPerPos, | 1335 const SkScalar pos[], int scalarsPerPos, |
1287 const SkPoint& offset, const SkPaint& srcPaint) { | 1336 const SkPoint& offset, const SkPaint& srcPaint) { |
| 1337 if (!SkPDFFont::CanEmbedTypeface(srcPaint.getTypeface(), fCanon)) { |
| 1338 const SkPoint* positions = reinterpret_cast<const SkPoint*>(pos); |
| 1339 SkAutoTMalloc<SkPoint> positionsBuffer; |
| 1340 if (2 != scalarsPerPos) { |
| 1341 int glyphCount = srcPaint.textToGlyphs(text, len, NULL); |
| 1342 positionsBuffer.reset(glyphCount); |
| 1343 for (int i = 0; i < glyphCount; ++i) { |
| 1344 positionsBuffer[i].set(pos[i], 0.0f); |
| 1345 } |
| 1346 positions = &positionsBuffer[0]; |
| 1347 } |
| 1348 SkPath path; |
| 1349 srcPaint.getPosTextPath(text, len, positions, &path); |
| 1350 SkMatrix matrix; |
| 1351 matrix.setTranslate(offset); |
| 1352 this->drawPath(d, path, srcPaint, &matrix, true); |
| 1353 // Draw text transparently to make it copyable/searchable/accessable. |
| 1354 draw_transparent_text( |
| 1355 this, d, text, len, offset.x() + positions[0].x(), |
| 1356 offset.y() + positions[0].y(), srcPaint); |
| 1357 return; |
| 1358 } |
| 1359 |
1288 SkPaint paint = srcPaint; | 1360 SkPaint paint = srcPaint; |
1289 replace_srcmode_on_opaque_paint(&paint); | 1361 replace_srcmode_on_opaque_paint(&paint); |
1290 | 1362 |
1291 NOT_IMPLEMENTED(paint.getMaskFilter() != nullptr, false); | 1363 NOT_IMPLEMENTED(paint.getMaskFilter() != nullptr, false); |
1292 if (paint.getMaskFilter() != nullptr) { | 1364 if (paint.getMaskFilter() != nullptr) { |
1293 // Don't pretend we support drawing MaskFilters, it makes for artifacts | 1365 // Don't pretend we support drawing MaskFilters, it makes for artifacts |
1294 // making text unreadable (e.g. same text twice when using CSS shadows). | 1366 // making text unreadable (e.g. same text twice when using CSS shadows). |
1295 return; | 1367 return; |
1296 } | 1368 } |
1297 SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos); | 1369 SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos); |
(...skipping 993 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2291 if (!pdfimage) { | 2363 if (!pdfimage) { |
2292 pdfimage.reset(SkPDFCreateBitmapObject(image)); | 2364 pdfimage.reset(SkPDFCreateBitmapObject(image)); |
2293 if (!pdfimage) { | 2365 if (!pdfimage) { |
2294 return; | 2366 return; |
2295 } | 2367 } |
2296 fCanon->addPDFBitmap(image->uniqueID(), pdfimage); | 2368 fCanon->addPDFBitmap(image->uniqueID(), pdfimage); |
2297 } | 2369 } |
2298 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()), | 2370 SkPDFUtils::DrawFormXObject(this->addXObjectResource(pdfimage.get()), |
2299 &content.entry()->fContent); | 2371 &content.entry()->fContent); |
2300 } | 2372 } |
OLD | NEW |