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); |
219 }; | 222 }; |
220 | 223 |
221 /////////////////////////////////////////////////////////////////////////// | 224 /////////////////////////////////////////////////////////////////////////// |
222 /////////////////////////////////////////////////////////////////////////// | 225 /////////////////////////////////////////////////////////////////////////// |
223 | 226 |
224 struct SkFaceRec { | 227 struct SkFaceRec { |
225 SkFaceRec* fNext; | 228 SkFaceRec* fNext; |
226 FT_Face fFace; | 229 FT_Face fFace; |
227 FT_StreamRec fFTStream; | 230 FT_StreamRec fFTStream; |
228 SkStream* fSkStream; | 231 SkStream* fSkStream; |
(...skipping 900 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1129 bbox->yMax += vector.y; | 1132 bbox->yMax += vector.y; |
1130 } | 1133 } |
1131 } | 1134 } |
1132 | 1135 |
1133 bool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) { | 1136 bool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) { |
1134 const FT_UInt glyph_id = FT_Get_Char_Index(fFace, letter); | 1137 const FT_UInt glyph_id = FT_Get_Char_Index(fFace, letter); |
1135 if (!glyph_id) | 1138 if (!glyph_id) |
1136 return false; | 1139 return false; |
1137 if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0) | 1140 if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0) |
1138 return false; | 1141 return false; |
1139 if ((fRec.fFlags & kEmbolden_Flag) && | 1142 emboldenIfNeeded(fFace, fFace->glyph); |
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); |
1192 | 1193 |
1193 switch ( fFace->glyph->format ) { | 1194 switch ( fFace->glyph->format ) { |
1194 case FT_GLYPH_FORMAT_OUTLINE: | 1195 case FT_GLYPH_FORMAT_OUTLINE: |
1195 if (0 == fFace->glyph->outline.n_contours) { | 1196 if (0 == fFace->glyph->outline.n_contours) { |
1196 glyph->fWidth = 0; | 1197 glyph->fWidth = 0; |
1197 glyph->fHeight = 0; | 1198 glyph->fHeight = 0; |
1198 glyph->fTop = 0; | 1199 glyph->fTop = 0; |
1199 glyph->fLeft = 0; | 1200 glyph->fLeft = 0; |
1200 } else { | 1201 } else { |
1201 if (fRec.fFlags & kEmbolden_Flag && !(fFace->style_flags & FT_STYLE_
FLAG_BOLD)) { | |
1202 emboldenOutline(fFace, &fFace->glyph->outline); | |
1203 } | |
1204 | |
1205 FT_BBox bbox; | 1202 FT_BBox bbox; |
1206 getBBoxForCurrentGlyph(glyph, &bbox, true); | 1203 getBBoxForCurrentGlyph(glyph, &bbox, true); |
1207 | 1204 |
1208 glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin)); | 1205 glyph->fWidth = SkToU16(SkFDot6Floor(bbox.xMax - bbox.xMin)); |
1209 glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin)); | 1206 glyph->fHeight = SkToU16(SkFDot6Floor(bbox.yMax - bbox.yMin)); |
1210 glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax)); | 1207 glyph->fTop = -SkToS16(SkFDot6Floor(bbox.yMax)); |
1211 glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin)); | 1208 glyph->fLeft = SkToS16(SkFDot6Floor(bbox.xMin)); |
1212 | 1209 |
1213 updateGlyphIfLCD(glyph); | 1210 updateGlyphIfLCD(glyph); |
1214 } | 1211 } |
1215 break; | 1212 break; |
1216 | 1213 |
1217 case FT_GLYPH_FORMAT_BITMAP: | 1214 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 | |
1223 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { | 1215 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { |
1224 FT_Vector vector; | 1216 FT_Vector vector; |
1225 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metric
s.horiBearingX; | 1217 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metric
s.horiBearingX; |
1226 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metri
cs.horiBearingY; | 1218 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metri
cs.horiBearingY; |
1227 FT_Vector_Transform(&vector, &fMatrix22); | 1219 FT_Vector_Transform(&vector, &fMatrix22); |
1228 fFace->glyph->bitmap_left += SkFDot6Floor(vector.x); | 1220 fFace->glyph->bitmap_left += SkFDot6Floor(vector.x); |
1229 fFace->glyph->bitmap_top += SkFDot6Floor(vector.y); | 1221 fFace->glyph->bitmap_top += SkFDot6Floor(vector.y); |
1230 } | 1222 } |
1231 | 1223 |
1232 if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) { | 1224 if (fFace->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_BGRA) { |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1291 | 1283 |
1292 err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFla
gs); | 1284 err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), fLoadGlyphFla
gs); |
1293 if (err != 0) { | 1285 if (err != 0) { |
1294 SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:
%d width:%d height:%d rb:%d flags:%d) returned 0x%x\n", | 1286 SkDEBUGF(("SkScalerContext_FreeType::generateImage: FT_Load_Glyph(glyph:
%d width:%d height:%d rb:%d flags:%d) returned 0x%x\n", |
1295 glyph.getGlyphID(fBaseGlyphCount), glyph.fWidth, glyph.fHeig
ht, glyph.rowBytes(), fLoadGlyphFlags, err)); | 1287 glyph.getGlyphID(fBaseGlyphCount), glyph.fWidth, glyph.fHeig
ht, glyph.rowBytes(), fLoadGlyphFlags, err)); |
1296 ERROR: | 1288 ERROR: |
1297 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); | 1289 memset(glyph.fImage, 0, glyph.rowBytes() * glyph.fHeight); |
1298 return; | 1290 return; |
1299 } | 1291 } |
1300 | 1292 |
| 1293 emboldenIfNeeded(fFace, fFace->glyph); |
1301 generateGlyphImage(fFace, glyph); | 1294 generateGlyphImage(fFace, glyph); |
1302 } | 1295 } |
1303 | 1296 |
1304 | 1297 |
1305 void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, | 1298 void SkScalerContext_FreeType::generatePath(const SkGlyph& glyph, |
1306 SkPath* path) { | 1299 SkPath* path) { |
1307 SkAutoMutexAcquire ac(gFTMutex); | 1300 SkAutoMutexAcquire ac(gFTMutex); |
1308 | 1301 |
1309 SkASSERT(&glyph && path); | 1302 SkASSERT(&glyph && path); |
1310 | 1303 |
1311 if (this->setupSize()) { | 1304 if (this->setupSize()) { |
1312 path->reset(); | 1305 path->reset(); |
1313 return; | 1306 return; |
1314 } | 1307 } |
1315 | 1308 |
1316 uint32_t flags = fLoadGlyphFlags; | 1309 uint32_t flags = fLoadGlyphFlags; |
1317 flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get
the outline | 1310 flags |= FT_LOAD_NO_BITMAP; // ignore embedded bitmaps so we're sure to get
the outline |
1318 flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline) | 1311 flags &= ~FT_LOAD_RENDER; // don't scan convert (we just want the outline) |
1319 | 1312 |
1320 FT_Error err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), flag
s); | 1313 FT_Error err = FT_Load_Glyph( fFace, glyph.getGlyphID(fBaseGlyphCount), flag
s); |
1321 | 1314 |
1322 if (err != 0) { | 1315 if (err != 0) { |
1323 SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%
d flags:%d) returned 0x%x\n", | 1316 SkDEBUGF(("SkScalerContext_FreeType::generatePath: FT_Load_Glyph(glyph:%
d flags:%d) returned 0x%x\n", |
1324 glyph.getGlyphID(fBaseGlyphCount), flags, err)); | 1317 glyph.getGlyphID(fBaseGlyphCount), flags, err)); |
1325 path->reset(); | 1318 path->reset(); |
1326 return; | 1319 return; |
1327 } | 1320 } |
| 1321 emboldenIfNeeded(fFace, fFace->glyph); |
1328 | 1322 |
1329 generateGlyphPath(fFace, path); | 1323 generateGlyphPath(fFace, path); |
1330 | 1324 |
1331 // The path's origin from FreeType is always the horizontal layout origin. | 1325 // The path's origin from FreeType is always the horizontal layout origin. |
1332 // Offset the path so that it is relative to the vertical origin if needed. | 1326 // Offset the path so that it is relative to the vertical origin if needed. |
1333 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { | 1327 if (fRec.fFlags & SkScalerContext::kVertical_Flag) { |
1334 FT_Vector vector; | 1328 FT_Vector vector; |
1335 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.ho
riBearingX; | 1329 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.ho
riBearingX; |
1336 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.h
oriBearingY; | 1330 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.h
oriBearingY; |
1337 FT_Vector_Transform(&vector, &fMatrix22); | 1331 FT_Vector_Transform(&vector, &fMatrix22); |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1459 my->fBottom = ymin * myy; | 1453 my->fBottom = ymin * myy; |
1460 my->fLeading = leading * myy; | 1454 my->fLeading = leading * myy; |
1461 my->fAvgCharWidth = avgCharWidth * myy; | 1455 my->fAvgCharWidth = avgCharWidth * myy; |
1462 my->fXMin = xmin; | 1456 my->fXMin = xmin; |
1463 my->fXMax = xmax; | 1457 my->fXMax = xmax; |
1464 my->fXHeight = x_height; | 1458 my->fXHeight = x_height; |
1465 my->fCapHeight = cap_height; | 1459 my->fCapHeight = cap_height; |
1466 } | 1460 } |
1467 } | 1461 } |
1468 | 1462 |
| 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 |
1469 /////////////////////////////////////////////////////////////////////////////// | 1482 /////////////////////////////////////////////////////////////////////////////// |
1470 | 1483 |
1471 #include "SkUtils.h" | 1484 #include "SkUtils.h" |
1472 | 1485 |
1473 static SkUnichar next_utf8(const void** chars) { | 1486 static SkUnichar next_utf8(const void** chars) { |
1474 return SkUTF8_NextUnichar((const char**)chars); | 1487 return SkUTF8_NextUnichar((const char**)chars); |
1475 } | 1488 } |
1476 | 1489 |
1477 static SkUnichar next_utf16(const void** chars) { | 1490 static SkUnichar next_utf16(const void** chars) { |
1478 return SkUTF16_NextUnichar((const uint16_t**)chars); | 1491 return SkUTF16_NextUnichar((const uint16_t**)chars); |
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1662 *style = (SkTypeface::Style) tempStyle; | 1675 *style = (SkTypeface::Style) tempStyle; |
1663 } | 1676 } |
1664 if (isFixedPitch) { | 1677 if (isFixedPitch) { |
1665 *isFixedPitch = FT_IS_FIXED_WIDTH(face); | 1678 *isFixedPitch = FT_IS_FIXED_WIDTH(face); |
1666 } | 1679 } |
1667 | 1680 |
1668 FT_Done_Face(face); | 1681 FT_Done_Face(face); |
1669 FT_Done_FreeType(library); | 1682 FT_Done_FreeType(library); |
1670 return true; | 1683 return true; |
1671 } | 1684 } |
OLD | NEW |