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

Side by Side Diff: src/ports/SkFontHost_FreeType.cpp

Issue 101333004: Supports the cap height for FreeType even when TT OS2 version is 1. (Closed) Base URL: https://chromium.googlesource.com/external/skia/src.git@master
Patch Set: Addressed review comments. Created 7 years 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
« no previous file with comments | « include/core/SkPaint.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
(...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after
206 bool fDoLinearMetrics; 206 bool fDoLinearMetrics;
207 bool fLCDIsVert; 207 bool fLCDIsVert;
208 208
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 // Caller must lock gFTMutex before calling this function. 217 // Caller must lock gFTMutex before calling this function.
217 void updateGlyphIfLCD(SkGlyph* glyph); 218 void updateGlyphIfLCD(SkGlyph* glyph);
218 }; 219 };
219 220
220 /////////////////////////////////////////////////////////////////////////// 221 ///////////////////////////////////////////////////////////////////////////
221 /////////////////////////////////////////////////////////////////////////// 222 ///////////////////////////////////////////////////////////////////////////
222 223
223 struct SkFaceRec { 224 struct SkFaceRec {
224 SkFaceRec* fNext; 225 SkFaceRec* fNext;
225 FT_Face fFace; 226 FT_Face fFace;
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 return (os2_table->fsType & 0x202) == 0; 425 return (os2_table->fsType & 0x202) == 0;
425 } 426 }
426 return false; // We tried, fail safe. 427 return false; // We tried, fail safe.
427 #endif 428 #endif
428 } 429 }
429 430
430 static bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) { 431 static bool GetLetterCBox(FT_Face face, char letter, FT_BBox* bbox) {
431 const FT_UInt glyph_id = FT_Get_Char_Index(face, letter); 432 const FT_UInt glyph_id = FT_Get_Char_Index(face, letter);
432 if (!glyph_id) 433 if (!glyph_id)
433 return false; 434 return false;
434 FT_Load_Glyph(face, glyph_id, FT_LOAD_NO_SCALE); 435 if (FT_Load_Glyph(face, glyph_id, FT_LOAD_NO_SCALE) != 0)
436 return false;
435 FT_Outline_Get_CBox(&face->glyph->outline, bbox); 437 FT_Outline_Get_CBox(&face->glyph->outline, bbox);
436 return true; 438 return true;
437 } 439 }
438 440
439 static bool getWidthAdvance(FT_Face face, int gId, int16_t* data) { 441 static bool getWidthAdvance(FT_Face face, int gId, int16_t* data) {
440 FT_Fixed advance = 0; 442 FT_Fixed advance = 0;
441 if (getAdvances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) { 443 if (getAdvances(face, gId, 1, FT_LOAD_NO_SCALE, &advance)) {
442 return false; 444 return false;
443 } 445 }
444 SkASSERT(data); 446 SkASSERT(data);
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
575 577
576 TT_PCLT* pclt_info; 578 TT_PCLT* pclt_info;
577 TT_OS2* os2_table; 579 TT_OS2* os2_table;
578 if ((pclt_info = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != NULL) { 580 if ((pclt_info = (TT_PCLT*)FT_Get_Sfnt_Table(face, ft_sfnt_pclt)) != NULL) {
579 info->fCapHeight = pclt_info->CapHeight; 581 info->fCapHeight = pclt_info->CapHeight;
580 uint8_t serif_style = pclt_info->SerifStyle & 0x3F; 582 uint8_t serif_style = pclt_info->SerifStyle & 0x3F;
581 if (serif_style >= 2 && serif_style <= 6) 583 if (serif_style >= 2 && serif_style <= 6)
582 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style; 584 info->fStyle |= SkAdvancedTypefaceMetrics::kSerif_Style;
583 else if (serif_style >= 9 && serif_style <= 12) 585 else if (serif_style >= 9 && serif_style <= 12)
584 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style; 586 info->fStyle |= SkAdvancedTypefaceMetrics::kScript_Style;
585 } else if ((os2_table = 587 } else if (((os2_table = (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != N ULL) &&
586 (TT_OS2*)FT_Get_Sfnt_Table(face, ft_sfnt_os2)) != NULL) { 588 // sCapHeight is available only when version 2 or later.
589 os2_table->version != 0xFFFF &&
590 os2_table->version >= 2) {
587 info->fCapHeight = os2_table->sCapHeight; 591 info->fCapHeight = os2_table->sCapHeight;
588 } else { 592 } else {
589 // Figure out a good guess for CapHeight: average the height of M and X. 593 // Figure out a good guess for CapHeight: average the height of M and X.
590 FT_BBox m_bbox, x_bbox; 594 FT_BBox m_bbox, x_bbox;
591 bool got_m, got_x; 595 bool got_m, got_x;
592 got_m = GetLetterCBox(face, 'M', &m_bbox); 596 got_m = GetLetterCBox(face, 'M', &m_bbox);
593 got_x = GetLetterCBox(face, 'X', &x_bbox); 597 got_x = GetLetterCBox(face, 'X', &x_bbox);
594 if (got_m && got_x) { 598 if (got_m && got_x) {
595 info->fCapHeight = (m_bbox.yMax - m_bbox.yMin + x_bbox.yMax - 599 info->fCapHeight = (m_bbox.yMax - m_bbox.yMin + x_bbox.yMax -
596 x_bbox.yMin) / 2; 600 x_bbox.yMin) / 2;
(...skipping 522 matching lines...) Expand 10 before | Expand all | Expand 10 after
1119 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.ho riBearingX; 1123 vector.x = fFace->glyph->metrics.vertBearingX - fFace->glyph->metrics.ho riBearingX;
1120 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.h oriBearingY; 1124 vector.y = -fFace->glyph->metrics.vertBearingY - fFace->glyph->metrics.h oriBearingY;
1121 FT_Vector_Transform(&vector, &fMatrix22); 1125 FT_Vector_Transform(&vector, &fMatrix22);
1122 bbox->xMin += vector.x; 1126 bbox->xMin += vector.x;
1123 bbox->xMax += vector.x; 1127 bbox->xMax += vector.x;
1124 bbox->yMin += vector.y; 1128 bbox->yMin += vector.y;
1125 bbox->yMax += vector.y; 1129 bbox->yMax += vector.y;
1126 } 1130 }
1127 } 1131 }
1128 1132
1133 bool SkScalerContext_FreeType::getCBoxForLetter(char letter, FT_BBox* bbox) {
1134 const FT_UInt glyph_id = FT_Get_Char_Index(fFace, letter);
1135 if (!glyph_id)
1136 return false;
1137 if (FT_Load_Glyph(fFace, glyph_id, fLoadGlyphFlags) != 0)
1138 return false;
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);
1144 return true;
1145 }
1146
1129 void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) { 1147 void SkScalerContext_FreeType::updateGlyphIfLCD(SkGlyph* glyph) {
1130 if (isLCD(fRec)) { 1148 if (isLCD(fRec)) {
1131 if (fLCDIsVert) { 1149 if (fLCDIsVert) {
1132 glyph->fHeight += gLCDExtra; 1150 glyph->fHeight += gLCDExtra;
1133 glyph->fTop -= gLCDExtra >> 1; 1151 glyph->fTop -= gLCDExtra >> 1;
1134 } else { 1152 } else {
1135 glyph->fWidth += gLCDExtra; 1153 glyph->fWidth += gLCDExtra;
1136 glyph->fLeft -= gLCDExtra >> 1; 1154 glyph->fLeft -= gLCDExtra >> 1;
1137 } 1155 }
1138 } 1156 }
(...skipping 212 matching lines...) Expand 10 before | Expand all | Expand 10 after
1351 if (!upem) { 1369 if (!upem) {
1352 TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head); 1370 TT_Header* ttHeader = (TT_Header*)FT_Get_Sfnt_Table(face, ft_sfnt_head);
1353 if (ttHeader) { 1371 if (ttHeader) {
1354 upem = SkIntToScalar(ttHeader->Units_Per_EM); 1372 upem = SkIntToScalar(ttHeader->Units_Per_EM);
1355 } 1373 }
1356 } 1374 }
1357 1375
1358 // use the os/2 table as a source of reasonable defaults. 1376 // use the os/2 table as a source of reasonable defaults.
1359 SkScalar x_height = 0.0f; 1377 SkScalar x_height = 0.0f;
1360 SkScalar avgCharWidth = 0.0f; 1378 SkScalar avgCharWidth = 0.0f;
1379 SkScalar cap_height = 0.0f;
1361 TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2); 1380 TT_OS2* os2 = (TT_OS2*) FT_Get_Sfnt_Table(face, ft_sfnt_os2);
1362 if (os2) { 1381 if (os2) {
1363 x_height = scaleX * SkIntToScalar(os2->sxHeight) / upem; 1382 x_height = scaleX * SkIntToScalar(os2->sxHeight) / upem;
1364 avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem; 1383 avgCharWidth = SkIntToScalar(os2->xAvgCharWidth) / upem;
1384 if (os2->version != 0xFFFF && os2->version >= 2) {
1385 cap_height = scaleX * SkIntToScalar(os2->sCapHeight) / upem;
1386 }
1365 } 1387 }
1366 1388
1367 // pull from format-specific metrics as needed 1389 // pull from format-specific metrics as needed
1368 SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax; 1390 SkScalar ascent, descent, leading, xmin, xmax, ymin, ymax;
1369 if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font 1391 if (face->face_flags & FT_FACE_FLAG_SCALABLE) { // scalable outline font
1370 ascent = -SkIntToScalar(face->ascender) / upem; 1392 ascent = -SkIntToScalar(face->ascender) / upem;
1371 descent = -SkIntToScalar(face->descender) / upem; 1393 descent = -SkIntToScalar(face->descender) / upem;
1372 leading = SkIntToScalar(face->height + (face->descender - face->ascender )) / upem; 1394 leading = SkIntToScalar(face->height + (face->descender - face->ascender )) / upem;
1373 xmin = SkIntToScalar(face->bbox.xMin) / upem; 1395 xmin = SkIntToScalar(face->bbox.xMin) / upem;
1374 xmax = SkIntToScalar(face->bbox.xMax) / upem; 1396 xmax = SkIntToScalar(face->bbox.xMax) / upem;
1375 ymin = -SkIntToScalar(face->bbox.yMin) / upem; 1397 ymin = -SkIntToScalar(face->bbox.yMin) / upem;
1376 ymax = -SkIntToScalar(face->bbox.yMax) / upem; 1398 ymax = -SkIntToScalar(face->bbox.yMax) / upem;
1377 // we may be able to synthesize x_height from outline 1399 // we may be able to synthesize x_height and cap_height from outline
1378 if (!x_height) { 1400 if (!x_height) {
1379 const FT_UInt x_glyph = FT_Get_Char_Index(fFace, 'x'); 1401 FT_BBox bbox;
1380 if (x_glyph) { 1402 if (getCBoxForLetter('x', &bbox)) {
1381 FT_BBox bbox;
1382 FT_Load_Glyph(fFace, x_glyph, fLoadGlyphFlags);
1383 if ((fRec.fFlags & kEmbolden_Flag) && !(fFace->style_flags & FT_ STYLE_FLAG_BOLD)) {
1384 emboldenOutline(fFace, &fFace->glyph->outline);
1385 }
1386 FT_Outline_Get_CBox(&fFace->glyph->outline, &bbox);
1387 x_height = SkIntToScalar(bbox.yMax) / 64.0f; 1403 x_height = SkIntToScalar(bbox.yMax) / 64.0f;
1388 } 1404 }
1389 } 1405 }
1406 if (!cap_height) {
1407 FT_BBox bbox;
1408 if (getCBoxForLetter('H', &bbox)) {
1409 cap_height = SkIntToScalar(bbox.yMax) / 64.0f;
1410 }
1411 }
1390 } else if (fStrikeIndex != -1) { // bitmap strike metrics 1412 } else if (fStrikeIndex != -1) { // bitmap strike metrics
1391 SkScalar xppem = SkIntToScalar(face->size->metrics.x_ppem); 1413 SkScalar xppem = SkIntToScalar(face->size->metrics.x_ppem);
1392 SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem); 1414 SkScalar yppem = SkIntToScalar(face->size->metrics.y_ppem);
1393 ascent = -SkIntToScalar(face->size->metrics.ascender) / (yppem * 64.0f); 1415 ascent = -SkIntToScalar(face->size->metrics.ascender) / (yppem * 64.0f);
1394 descent = -SkIntToScalar(face->size->metrics.descender) / (yppem * 64.0f ); 1416 descent = -SkIntToScalar(face->size->metrics.descender) / (yppem * 64.0f );
1395 leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f)) 1417 leading = (SkIntToScalar(face->size->metrics.height) / (yppem * 64.0f))
1396 + ascent - descent; 1418 + ascent - descent;
1397 xmin = 0.0f; 1419 xmin = 0.0f;
1398 xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem; 1420 xmax = SkIntToScalar(face->available_sizes[fStrikeIndex].width) / xppem;
1399 ymin = descent + leading; 1421 ymin = descent + leading;
1400 ymax = ascent - descent; 1422 ymax = ascent - descent;
1401 if (!x_height) {
1402 x_height = -ascent;
1403 }
1404 if (!avgCharWidth) {
1405 avgCharWidth = xmax - xmin;
1406 }
1407 } else { 1423 } else {
1408 goto ERROR; 1424 goto ERROR;
1409 } 1425 }
1410 1426
1411 // synthesize elements that were not provided by the os/2 table or format-sp ecific metrics 1427 // synthesize elements that were not provided by the os/2 table or format-sp ecific metrics
1412 if (!x_height) { 1428 if (!x_height) {
1413 x_height = -ascent; 1429 x_height = -ascent;
1414 } 1430 }
1415 if (!avgCharWidth) { 1431 if (!avgCharWidth) {
1416 avgCharWidth = xmax - xmin; 1432 avgCharWidth = xmax - xmin;
1417 } 1433 }
1434 if (!cap_height) {
1435 cap_height = -ascent;
1436 }
1418 1437
1419 // disallow negative linespacing 1438 // disallow negative linespacing
1420 if (leading < 0.0f) { 1439 if (leading < 0.0f) {
1421 leading = 0.0f; 1440 leading = 0.0f;
1422 } 1441 }
1423 1442
1424 if (mx) { 1443 if (mx) {
1425 mx->fTop = ymax * mxy; 1444 mx->fTop = ymax * mxy;
1426 mx->fAscent = ascent * mxy; 1445 mx->fAscent = ascent * mxy;
1427 mx->fDescent = descent * mxy; 1446 mx->fDescent = descent * mxy;
1428 mx->fBottom = ymin * mxy; 1447 mx->fBottom = ymin * mxy;
1429 mx->fLeading = leading * mxy; 1448 mx->fLeading = leading * mxy;
1430 mx->fAvgCharWidth = avgCharWidth * mxy; 1449 mx->fAvgCharWidth = avgCharWidth * mxy;
1431 mx->fXMin = xmin; 1450 mx->fXMin = xmin;
1432 mx->fXMax = xmax; 1451 mx->fXMax = xmax;
1433 mx->fXHeight = x_height; 1452 mx->fXHeight = x_height;
1453 mx->fCapHeight = cap_height;
1434 } 1454 }
1435 if (my) { 1455 if (my) {
1436 my->fTop = ymax * myy; 1456 my->fTop = ymax * myy;
1437 my->fAscent = ascent * myy; 1457 my->fAscent = ascent * myy;
1438 my->fDescent = descent * myy; 1458 my->fDescent = descent * myy;
1439 my->fBottom = ymin * myy; 1459 my->fBottom = ymin * myy;
1440 my->fLeading = leading * myy; 1460 my->fLeading = leading * myy;
1441 my->fAvgCharWidth = avgCharWidth * myy; 1461 my->fAvgCharWidth = avgCharWidth * myy;
1442 my->fXMin = xmin; 1462 my->fXMin = xmin;
1443 my->fXMax = xmax; 1463 my->fXMax = xmax;
1444 my->fXHeight = x_height; 1464 my->fXHeight = x_height;
1465 my->fCapHeight = cap_height;
1445 } 1466 }
1446 } 1467 }
1447 1468
1448 /////////////////////////////////////////////////////////////////////////////// 1469 ///////////////////////////////////////////////////////////////////////////////
1449 1470
1450 #include "SkUtils.h" 1471 #include "SkUtils.h"
1451 1472
1452 static SkUnichar next_utf8(const void** chars) { 1473 static SkUnichar next_utf8(const void** chars) {
1453 return SkUTF8_NextUnichar((const char**)chars); 1474 return SkUTF8_NextUnichar((const char**)chars);
1454 } 1475 }
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
1641 *style = (SkTypeface::Style) tempStyle; 1662 *style = (SkTypeface::Style) tempStyle;
1642 } 1663 }
1643 if (isFixedPitch) { 1664 if (isFixedPitch) {
1644 *isFixedPitch = FT_IS_FIXED_WIDTH(face); 1665 *isFixedPitch = FT_IS_FIXED_WIDTH(face);
1645 } 1666 }
1646 1667
1647 FT_Done_Face(face); 1668 FT_Done_Face(face);
1648 FT_Done_FreeType(library); 1669 FT_Done_FreeType(library);
1649 return true; 1670 return true;
1650 } 1671 }
OLDNEW
« no previous file with comments | « include/core/SkPaint.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698