Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/pdf/SkPDFDevice.cpp

Issue 24364008: Update PDF backend to support fallback fonts on Android. (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 15 matching lines...) Expand all
26 #include "SkPDFStream.h" 26 #include "SkPDFStream.h"
27 #include "SkPDFTypes.h" 27 #include "SkPDFTypes.h"
28 #include "SkPDFUtils.h" 28 #include "SkPDFUtils.h"
29 #include "SkRect.h" 29 #include "SkRect.h"
30 #include "SkString.h" 30 #include "SkString.h"
31 #include "SkTextFormatParams.h" 31 #include "SkTextFormatParams.h"
32 #include "SkTemplates.h" 32 #include "SkTemplates.h"
33 #include "SkTypefacePriv.h" 33 #include "SkTypefacePriv.h"
34 #include "SkTSet.h" 34 #include "SkTSet.h"
35 35
36 #ifdef SK_BUILD_FOR_ANDROID
37 #include "SkTypeface_android.h"
38
39 struct TypefaceData {
40 int lowerBounds;
41 int upperBounds;
42 };
43 #endif
44
36 // Utility functions 45 // Utility functions
37 46
38 static void emit_pdf_color(SkColor color, SkWStream* result) { 47 static void emit_pdf_color(SkColor color, SkWStream* result) {
39 SkASSERT(SkColorGetA(color) == 0xFF); // We handle alpha elsewhere. 48 SkASSERT(SkColorGetA(color) == 0xFF); // We handle alpha elsewhere.
40 SkScalar colorMax = SkIntToScalar(0xFF); 49 SkScalar colorMax = SkIntToScalar(0xFF);
41 SkPDFScalar::Append( 50 SkPDFScalar::Append(
42 SkScalarDiv(SkIntToScalar(SkColorGetR(color)), colorMax), result); 51 SkScalarDiv(SkIntToScalar(SkColorGetR(color)), colorMax), result);
43 result->writeText(" "); 52 result->writeText(" ");
44 SkPDFScalar::Append( 53 SkPDFScalar::Append(
45 SkScalarDiv(SkIntToScalar(SkColorGetG(color)), colorMax), result); 54 SkScalarDiv(SkIntToScalar(SkColorGetG(color)), colorMax), result);
(...skipping 1062 matching lines...) Expand 10 before | Expand all | Expand 10 after
1108 // making text unreadable (e.g. same text twice when using CSS shadows). 1117 // making text unreadable (e.g. same text twice when using CSS shadows).
1109 return; 1118 return;
1110 } 1119 }
1111 SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos); 1120 SkASSERT(1 == scalarsPerPos || 2 == scalarsPerPos);
1112 SkPaint textPaint = calculate_text_paint(paint); 1121 SkPaint textPaint = calculate_text_paint(paint);
1113 ScopedContentEntry content(this, d, textPaint, true); 1122 ScopedContentEntry content(this, d, textPaint, true);
1114 if (!content.entry()) { 1123 if (!content.entry()) {
1115 return; 1124 return;
1116 } 1125 }
1117 1126
1127 #ifdef SK_BUILD_FOR_ANDROID
1128 /*
1129 * In the case that we have enabled fallback fonts on Android we need to
1130 * take the following steps to ensure that the PDF draws all characters,
1131 * regardless of their underlying font file, correctly.
1132 *
1133 * 1. Convert input into GlyphID encoding if it currently is not
1134 * 2. Iterate over the glyphIDs and identify the actual typeface that each
1135 * glyph resolves to
1136 * 3. Iterate over those typefaces and recursively call this function with
1137 * only the glyphs (and their positions) that the typeface is capable of
1138 * resolving.
1139 */
1140 if (paint.getPaintOptionsAndroid().isUsingFontFallbacks()) {
1141 uint16_t* glyphIDs = NULL;
reed1 2013/09/24 20:10:19 can this guy be const?
1142 SkGlyphStorage tmpStorage(0);
1143 size_t numGlyphs = 0;
1144
1145 // convert to glyphIDs
1146 if (paint.getTextEncoding() != SkPaint::kGlyphID_TextEncoding) {
1147 numGlyphs = paint.textToGlyphs(text, len, NULL);
1148 tmpStorage.reset(numGlyphs);
1149 paint.textToGlyphs(text, len, tmpStorage.get());
1150 glyphIDs = tmpStorage.get();
1151 } else {
1152 numGlyphs = len / 2;
1153 glyphIDs = reinterpret_cast<uint16_t*>(const_cast<void*>((text)));
reed1 2013/09/24 20:10:19 nit: that's a lot (of) ((parens))
1154 }
1155
1156 // if no typeface is provided in the paint get the default
1157 SkAutoTUnref<SkTypeface> origFace(SkSafeRef(paint.getTypeface()));
1158 if (!origFace.get()) {
1159 origFace.reset(SkTypeface::RefDefault());
1160 }
1161 const uint16_t origGlyphCount = origFace->countGlyphs();
1162
1163 // keep a list of the already visited typefaces and some data about them
1164 SkTDArray<SkTypeface*> visitedTypefaces;
1165 SkTDArray<TypefaceData> typefaceData;
reed1 2013/09/24 20:10:19 Can these two arrays be folded into a single one,
1166
1167 // find all the typefaces needed to resolve this run of text
1168 bool usesOriginalTypeface = false;
1169 for (uint16_t x = 0; x < numGlyphs; ++x) {
1170 // optimization that checks to see if original typeface can resolve the glyph
1171 if (glyphIDs[x] < origGlyphCount) {
1172 usesOriginalTypeface = true;
1173 continue;
1174 }
1175
1176 // find the fallback typeface that supports this glyph
1177 int lBounds, uBounds;
1178 SkTypeface* fallbackTypeface = SkGetTypefaceForGlyphID(glyphIDs[x],
1179 origFace.get( ),
1180 paint.getPain tOptionsAndroid(),
1181 &lBounds, &uB ounds);
1182 // if there is no valid typeface then we just skip the glyph
1183 if (!fallbackTypeface) {
1184 continue;
1185 }
1186
1187 // check if we have already used this typeface
1188 if (visitedTypefaces.contains(fallbackTypeface)) {
1189 continue;
1190 }
1191
1192 // add the typeface and its data if we don't have it
1193 visitedTypefaces.push(fallbackTypeface);
1194 TypefaceData* data = typefaceData.push();
1195 data->lowerBounds = lBounds;
1196 data->upperBounds = uBounds;
1197 }
1198
1199 // if the original font was used then add it to the list as well
1200 if (usesOriginalTypeface) {
reed1 2013/09/24 20:10:19 In this case, can't we just call through to the or
djsollen 2013/09/24 20:44:17 We need to make the copy for the case when we have
1201 visitedTypefaces.push(SkSafeRef(origFace.get()));
reed1 2013/09/24 20:10:19 why do we need to ref() the typefaces?
1202 TypefaceData* data = typefaceData.push();
1203 data->lowerBounds = 0;
1204 data->upperBounds = origGlyphCount;
1205 }
1206
1207 // keep a scratch glyph and pos storage
1208 SkAutoTMalloc<SkScalar> posStorage(len * scalarsPerPos);
1209 SkScalar* tmpPos = posStorage.get();
1210 SkGlyphStorage glyphStorage(numGlyphs);
1211 uint16_t* tmpGlyphIDs = glyphStorage.get();
1212
1213 // loop through all the valid typefaces, trim the glyphs to only those
1214 // resolved by the typeface, and then draw that run of glyphs
1215 for (int x = 0; x < visitedTypefaces.count(); ++x) {
1216 SkTypeface* typeface = visitedTypefaces[x];
1217 const TypefaceData& data = typefaceData[x];
1218
1219 int tmpGlyphCount = 0;
1220 for (uint16_t y = 0; y < numGlyphs; ++y) {
1221 if (glyphIDs[y] >= data.lowerBounds && glyphIDs[y] < data.upperB ounds) {
1222 tmpGlyphIDs[tmpGlyphCount] = glyphIDs[y] - data.lowerBounds;
1223 memcpy(&(tmpPos[tmpGlyphCount * scalarsPerPos]),
1224 &(pos[y * scalarsPerPos]),
1225 scalarsPerPos * sizeof(SkScalar));
1226 tmpGlyphCount++;
1227 }
1228 }
1229
1230 // recursively call this function with the right typeface
1231 SkPaint tmpPaint = paint;
1232 tmpPaint.setTypeface(typeface);
1233 tmpPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
1234
1235 // turn off fallback chaining
1236 SkPaintOptionsAndroid paintOpts = tmpPaint.getPaintOptionsAndroid();
1237 paintOpts.setUseFontFallbacks(false);
1238 tmpPaint.setPaintOptionsAndroid(paintOpts);
1239
1240 this->drawPosText(d, tmpGlyphIDs, tmpGlyphCount * 2, tmpPos, constY,
1241 scalarsPerPos, tmpPaint);
1242 }
1243
1244 visitedTypefaces.safeUnrefAll();
1245 return;
1246 }
1247 #endif
1248
1118 SkGlyphStorage storage(0); 1249 SkGlyphStorage storage(0);
1119 uint16_t* glyphIDs = NULL; 1250 uint16_t* glyphIDs = NULL;
1120 size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage, 1251 size_t numGlyphs = force_glyph_encoding(paint, text, len, &storage,
1121 &glyphIDs); 1252 &glyphIDs);
1122 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); 1253 textPaint.setTextEncoding(SkPaint::kGlyphID_TextEncoding);
1123 1254
1124 SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc(); 1255 SkDrawCacheProc glyphCacheProc = textPaint.getDrawCacheProc();
1125 content.entry()->fContent.writeText("BT\n"); 1256 content.entry()->fContent.writeText("BT\n");
1126 updateFont(textPaint, glyphIDs[0], content.entry()); 1257 updateFont(textPaint, glyphIDs[0], content.entry());
1127 for (size_t i = 0; i < numGlyphs; i++) { 1258 for (size_t i = 0; i < numGlyphs; i++) {
(...skipping 808 matching lines...) Expand 10 before | Expand all | Expand 10 after
1936 } 2067 }
1937 2068
1938 bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y, 2069 bool SkPDFDevice::onReadPixels(const SkBitmap& bitmap, int x, int y,
1939 SkCanvas::Config8888) { 2070 SkCanvas::Config8888) {
1940 return false; 2071 return false;
1941 } 2072 }
1942 2073
1943 bool SkPDFDevice::allowImageFilter(SkImageFilter*) { 2074 bool SkPDFDevice::allowImageFilter(SkImageFilter*) {
1944 return false; 2075 return false;
1945 } 2076 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698