OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "SkBitmap.h" | 9 #include "SkBitmap.h" |
10 #include "SkCanvas.h" | 10 #include "SkCanvas.h" |
11 #include "SkColorPriv.h" | 11 #include "SkColorPriv.h" |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 // Need scalar versions for generateFontMetrics | 209 // Need scalar versions for generateFontMetrics |
210 SkVector fScale; | 210 SkVector fScale; |
211 SkMatrix fMatrix22Scalar; | 211 SkMatrix fMatrix22Scalar; |
212 | 212 |
213 FT_Error setupSize(); | 213 FT_Error setupSize(); |
214 void getBBoxForCurrentGlyph(SkGlyph* glyph, FT_BBox* bbox, | 214 void getBBoxForCurrentGlyph(SkGlyph* glyph, FT_BBox* bbox, |
215 bool snapToPixelBoundary = false); | 215 bool snapToPixelBoundary = false); |
216 bool getCBoxForLetter(char letter, FT_BBox* bbox); | 216 bool getCBoxForLetter(char letter, FT_BBox* bbox); |
217 // Caller must lock gFTMutex before calling this function. | 217 // Caller must lock gFTMutex before calling this function. |
218 void updateGlyphIfLCD(SkGlyph* glyph); | 218 void updateGlyphIfLCD(SkGlyph* glyph); |
219 // Caller must lock gFTMutex before calling this function. | |
220 // update FreeType2 glyph slot with glyph emboldened | |
221 void emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph); | |
222 }; | 219 }; |
223 | 220 |
224 /////////////////////////////////////////////////////////////////////////// | 221 /////////////////////////////////////////////////////////////////////////// |
225 /////////////////////////////////////////////////////////////////////////// | 222 /////////////////////////////////////////////////////////////////////////// |
226 | 223 |
227 struct SkFaceRec { | 224 struct SkFaceRec { |
228 SkFaceRec* fNext; | 225 SkFaceRec* fNext; |
229 FT_Face fFace; | 226 FT_Face fFace; |
230 FT_StreamRec fFTStream; | 227 FT_StreamRec fFTStream; |
231 SkStream* fSkStream; | 228 SkStream* fSkStream; |
(...skipping 900 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1132 bbox->yMax += vector.y; | 1129 bbox->yMax += vector.y; |
1133 } | 1130 } |
1134 } | 1131 } |
1135 | 1132 |
1136 bool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) { | 1133 bool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) { |
1137 const FT_UInt glyph_id = FT_Get_Char_Index(fFace, letter); | 1134 const FT_UInt glyph_id = FT_Get_Char_Index(fFace, letter); |
1138 if (!glyph_id) | 1135 if (!glyph_id) |
1139 return false; | 1136 return false; |
1140 if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0) | 1137 if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0) |
1141 return false; | 1138 return false; |
1142 emboldenIfNeeded(fFace, fFace->glyph); | 1139 if ((fRec.fFlags & kEmbolden_Flag) && |
| 1140 !(fFace->style_flags & FT_STYLE_FLAG_BOLD)) { |
| 1141 emboldenOutline(fFace, &fFace->glyph->outline); |
| 1142 } |
1143 FT_Outline_Get_CBox(&fFace->glyph->outline, bbox); | 1143 FT_Outline_Get_CBox(&fFace->glyph->outline, bbox); |
1144 return true; | 1144 return true; |
1145 } | 1145 } |
1146 | 1146 |
1147 void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) { | 1147 void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) { |
1148 if (isLCD(fRec)) { | 1148 if (isLCD(fRec)) { |
1149 if (fLCDIsVert) { | 1149 if (fLCDIsVert) { |
1150 glyph->fHeight += gLCDExtra; | 1150 glyph->fHeight += gLCDExtra; |
1151 glyph->fTop -= gLCDExtra >> 1; | 1151 glyph->fTop -= gLCDExtra >> 1; |
1152 } else { | 1152 } else { |
(...skipping 29 matching lines...) Expand all Loading... |
1182 err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFl
ags ); | 1182 err = FT_Load_Glyph( fFace, glyph->getGlyphID(fBaseGlyphCount), fLoadGlyphFl
ags ); |
1183 if (err != 0) { | 1183 if (err != 0) { |
1184 #if 0 | 1184 #if 0 |
1185 SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(
glyph:%d flags:%x) returned 0x%x\n", | 1185 SkDEBUGF(("SkScalerContext_FreeType::generateMetrics(%x): FT_Load_Glyph(
glyph:%d flags:%x) returned 0x%x\n", |
1186 fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoad
GlyphFlags, err)); | 1186 fFaceRec->fFontID, glyph->getGlyphID(fBaseGlyphCount), fLoad
GlyphFlags, err)); |
1187 #endif | 1187 #endif |
1188 ERROR: | 1188 ERROR: |
1189 glyph->zeroMetrics(); | 1189 glyph->zeroMetrics(); |
1190 return; | 1190 return; |
1191 } | 1191 } |
1192 emboldenIfNeeded(fFace, fFace->glyph); | |
1193 | 1192 |
1194 switch ( fFace->glyph->format ) { | 1193 switch ( fFace->glyph->format ) { |
1195 case FT_GLYPH_FORMAT_OUTLINE: | 1194 case FT_GLYPH_FORMAT_OUTLINE: |
1196 if (0 == fFace->glyph->outline.n_contours) { | 1195 if (0 == fFace->glyph->outline.n_contours) { |
1197 glyph->fWidth = 0; | 1196 glyph->fWidth = 0; |
1198 glyph->fHeight = 0; | 1197 glyph->fHeight = 0; |
1199 glyph->fTop = 0; | 1198 glyph->fTop = 0; |
1200 glyph->fLeft = 0; | 1199 glyph->fLeft = 0; |
1201 } else { | 1200 } else { |
| 1201 if (fRec.fFlags & kEmbolden_Flag && !(fFace->style_flags & FT_STYLE_
FLAG_BOLD)) { |
| 1202 emboldenOutline(fFace, &fFace->glyph->outline); |
| 1203 } |
| 1204 |
1202 FT_BBox bbox; | 1205 FT_BBox bbox; |
1203 getBBoxForCurrentGlyph(glyph, &bbox, true); | 1206 getBBoxForCurrentGlyph(glyph, &bbox, true); |
1204 | 1207 |
1205 glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin)); | 1208 glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin)); |
1206 glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin)); | 1209 glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin)); |
1207 glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax)); | 1210 glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax)); |
1208 glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin)); | 1211 glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin)); |
1209 | 1212 |
1210 updateGlyphIfLCD(glyph); | 1213 updateGlyphIfLCD(glyph); |
1211 } | 1214 } |
1212 break; | 1215 break; |
1213 | 1216 |
1214 case FT_GLYPH_FORMAT_BITMAP: | 1217 case FT_GLYPH_FORMAT_BITMAP: |
| 1218 if (fRec.fFlags & kEmbolden_Flag) { |
| 1219 FT_GlyphSlot_Own_Bitmap(fFace->glyph); |
| 1220 FT_Bitmap_Embolden(gFTLibrary, &fFace->glyph->bitmap, kBitmapEmbolde
nStrength, 0); |
| 1221 } |
| 1222 |
1215 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { | 1223 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { |
1216 FT_Vector vector; | 1224 FT_Vector vector; |
1217 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metric
s.horiBearingX; | 1225 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metric
s.horiBearingX; |
1218 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metri
cs.horiBearingY; | 1226 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metri
cs.horiBearingY; |
1219 FT_Vector_Transform(&vector, &fMatrix22); | 1227 FT_Vector_Transform(&vector, &fMatrix22); |
1220 fFace->glyph->bitmap_left += SkFDot6Floor(vector.x); | 1228 fFace->glyph->bitmap_left += SkFDot6Floor(vector.x); |
1221 fFace->glyph->bitmap_top += SkFDot6Floor(vector.y); | 1229 fFace->glyph->bitmap_top += SkFDot6Floor(vector.y); |
1222 } | 1230 } |
1223 | 1231 |
1224 if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) { | 1232 if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1283 | 1291 |
1284 err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFla
gs); | 1292 err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFla
gs); |
1285 if (err != 0) { | 1293 if (err != 0) { |
1286 SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:
%d width:%d height:%d rb:%d flags:%d) returned 0x%x\n", | 1294 SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:
%d width:%d height:%d rb:%d flags:%d) returned 0x%x\n", |
1287 glyph.getGlyphID(fBaseGlyphCount), glyph.fWidth, glyph.fHeig
ht, glyph.rowBytes(), fLoadGlyphFlags, err)); | 1295 glyph.getGlyphID(fBaseGlyphCount), glyph.fWidth, glyph.fHeig
ht, glyph.rowBytes(), fLoadGlyphFlags, err)); |
1288 ERROR: | 1296 ERROR: |
1289 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); | 1297 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); |
1290 return; | 1298 return; |
1291 } | 1299 } |
1292 | 1300 |
1293 emboldenIfNeeded(fFace, fFace->glyph); | |
1294 generateGlyphImage(fFace, glyph); | 1301 generateGlyphImage(fFace, glyph); |
1295 } | 1302 } |
1296 | 1303 |
1297 | 1304 |
1298 void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, | 1305 void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, |
1299 SkPath* path) { | 1306 SkPath* path) { |
1300 SkAutoMutexAcquire ac(gFTMutex); | 1307 SkAutoMutexAcquire ac(gFTMutex); |
1301 | 1308 |
1302 SkASSERT(&glyph && path); | 1309 SkASSERT(&glyph && path); |
1303 | 1310 |
1304 if (this->setupSize()) { | 1311 if (this->setupSize()) { |
1305 path->reset(); | 1312 path->reset(); |
1306 return; | 1313 return; |
1307 } | 1314 } |
1308 | 1315 |
1309 uint32_t flags = fLoadGlyphFlags; | 1316 uint32_t flags = fLoadGlyphFlags; |
1310 flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get
the outline | 1317 flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get
the outline |
1311 flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline) | 1318 flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline) |
1312 | 1319 |
1313 FT_Error err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), flag
s); | 1320 FT_Error err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), flag
s); |
1314 | 1321 |
1315 if (err != 0) { | 1322 if (err != 0) { |
1316 SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%
d flags:%d) returned 0x%x\n", | 1323 SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%
d flags:%d) returned 0x%x\n", |
1317 glyph.getGlyphID(fBaseGlyphCount), flags, err)); | 1324 glyph.getGlyphID(fBaseGlyphCount), flags, err)); |
1318 path->reset(); | 1325 path->reset(); |
1319 return; | 1326 return; |
1320 } | 1327 } |
1321 emboldenIfNeeded(fFace, fFace->glyph); | |
1322 | 1328 |
1323 generateGlyphPath(fFace, path); | 1329 generateGlyphPath(fFace, path); |
1324 | 1330 |
1325 // The path's origin from FreeType is always the horizontal layout origin. | 1331 // The path's origin from FreeType is always the horizontal layout origin. |
1326 // Offset the path so that it is relative to the vertical origin if needed. | 1332 // Offset the path so that it is relative to the vertical origin if needed. |
1327 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { | 1333 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { |
1328 FT_Vector vector; | 1334 FT_Vector vector; |
1329 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.ho
riBearingX; | 1335 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.ho
riBearingX; |
1330 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.h
oriBearingY; | 1336 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.h
oriBearingY; |
1331 FT_Vector_Transform(&vector, &fMatrix22); | 1337 FT_Vector_Transform(&vector, &fMatrix22); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1453 my->fBottom = ymin * myy; | 1459 my->fBottom = ymin * myy; |
1454 my->fLeading = leading * myy; | 1460 my->fLeading = leading * myy; |
1455 my->fAvgCharWidth = avgCharWidth * myy; | 1461 my->fAvgCharWidth = avgCharWidth * myy; |
1456 my->fXMin = xmin; | 1462 my->fXMin = xmin; |
1457 my->fXMax = xmax; | 1463 my->fXMax = xmax; |
1458 my->fXHeight = x_height; | 1464 my->fXHeight = x_height; |
1459 my->fCapHeight = cap_height; | 1465 my->fCapHeight = cap_height; |
1460 } | 1466 } |
1461 } | 1467 } |
1462 | 1468 |
1463 void SkScalerContext_FreeType::emboldenIfNeeded(FT_Face face, FT_GlyphSlot glyph
) | |
1464 { | |
1465 if (fRec.fFlags & SkScalerContext::kEmbolden_Flag) { | |
1466 switch ( glyph->format ) { | |
1467 case FT_GLYPH_FORMAT_OUTLINE: | |
1468 FT_Pos strength; | |
1469 strength = FT_MulFix(face->units_per_EM, face->size->metrics.y_s
cale) / 24; | |
1470 FT_Outline_Embolden(&glyph->outline, strength); | |
1471 break; | |
1472 case FT_GLYPH_FORMAT_BITMAP: | |
1473 FT_GlyphSlot_Own_Bitmap(glyph); | |
1474 FT_Bitmap_Embolden(glyph->library, &glyph->bitmap, kBitmapEmbold
enStrength, 0); | |
1475 break; | |
1476 default: | |
1477 SkDEBUGFAIL("unknown glyph format"); | |
1478 } | |
1479 } | |
1480 } | |
1481 | |
1482 /////////////////////////////////////////////////////////////////////////////// | 1469 /////////////////////////////////////////////////////////////////////////////// |
1483 | 1470 |
1484 #include "SkUtils.h" | 1471 #include "SkUtils.h" |
1485 | 1472 |
1486 static SkUnichar next_utf8(const void** chars) { | 1473 static SkUnichar next_utf8(const void** chars) { |
1487 return SkUTF8_NextUnichar((const char**)chars); | 1474 return SkUTF8_NextUnichar((const char**)chars); |
1488 } | 1475 } |
1489 | 1476 |
1490 static SkUnichar next_utf16(const void** chars) { | 1477 static SkUnichar next_utf16(const void** chars) { |
1491 return SkUTF16_NextUnichar((const uint16_t**)chars); | 1478 return SkUTF16_NextUnichar((const uint16_t**)chars); |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1675 *style = (SkTypeface::Style) tempStyle; | 1662 *style = (SkTypeface::Style) tempStyle; |
1676 } | 1663 } |
1677 if (isFixedPitch) { | 1664 if (isFixedPitch) { |
1678 *isFixedPitch = FT_IS_FIXED_WIDTH(face); | 1665 *isFixedPitch = FT_IS_FIXED_WIDTH(face); |
1679 } | 1666 } |
1680 | 1667 |
1681 FT_Done_Face(face); | 1668 FT_Done_Face(face); |
1682 FT_Done_FreeType(library); | 1669 FT_Done_FreeType(library); |
1683 return true; | 1670 return true; |
1684 } | 1671 } |
OLD | NEW |