|
Lines 173-187
Link Here
|
| 173 |
FT_Face |
173 |
FT_Face |
| 174 |
nsFreeTypeFont::getFTFace() |
174 |
nsFreeTypeFont::getFTFace() |
| 175 |
{ |
175 |
{ |
| 176 |
FT_Face face = nsnull; |
176 |
if (mFace) return mFace; |
| 177 |
FTC_Manager mgr; |
177 |
|
|
|
178 |
nsCAutoString fileName; |
| 179 |
PRInt16 faceIndex; |
| 180 |
mFaceID->GetFileName(fileName); |
| 181 |
mFaceID->GetFaceIndex(&faceIndex); |
| 182 |
|
| 178 |
nsresult rv; |
183 |
nsresult rv; |
| 179 |
mFt2->GetFTCacheManager(&mgr); |
184 |
rv = mFt2->NewFace(mFreeTypeLibrary, fileName.get(), faceIndex, &mFace); |
| 180 |
rv = mFt2->ManagerLookupSize(mgr, &mImageDesc.font, &face, nsnull); |
|
|
| 181 |
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get face/size"); |
185 |
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to get face/size"); |
| 182 |
if (NS_FAILED(rv)) |
186 |
if (NS_FAILED(rv)) |
| 183 |
return nsnull; |
187 |
return nsnull; |
| 184 |
return face; |
188 |
rv = mFt2->SetPixelSizes(mFace, mPixelSize, 0); |
|
|
189 |
if (NS_FAILED(rv)) |
| 190 |
return nsnull; |
| 191 |
return mFace; |
| 185 |
} |
192 |
} |
| 186 |
|
193 |
|
| 187 |
nsFreeTypeFont::nsFreeTypeFont(nsITrueTypeFontCatalogEntry *aFaceID, |
194 |
nsFreeTypeFont::nsFreeTypeFont(nsITrueTypeFontCatalogEntry *aFaceID, |
|
Lines 191-211
Link Here
|
| 191 |
PRBool embedded_bimap = PR_FALSE; |
198 |
PRBool embedded_bimap = PR_FALSE; |
| 192 |
mFaceID = aFaceID; |
199 |
mFaceID = aFaceID; |
| 193 |
mPixelSize = aPixelSize; |
200 |
mPixelSize = aPixelSize; |
| 194 |
mImageDesc.font.face_id = (void*)mFaceID; |
201 |
//mLoadFlag = FT_LOAD_RENDER; |
| 195 |
mImageDesc.font.pix_width = aPixelSize; |
202 |
mLoadFlag = 0; |
| 196 |
mImageDesc.font.pix_height = aPixelSize; |
203 |
mFace = nsnull; |
| 197 |
mImageDesc.image_type = 0; |
|
|
| 198 |
|
204 |
|
| 199 |
if (aPixelSize < nsFreeType2::gAntiAliasMinimum) { |
205 |
if (aPixelSize < nsFreeType2::gAntiAliasMinimum) { |
| 200 |
mImageDesc.image_type |= ftc_image_mono; |
206 |
mLoadFlag |= FT_LOAD_MONOCHROME; |
| 201 |
anti_alias = PR_FALSE; |
207 |
anti_alias = PR_FALSE; |
| 202 |
} |
208 |
} |
| 203 |
|
209 |
|
| 204 |
if (nsFreeType2::gFreeType2Autohinted) |
210 |
if (nsFreeType2::gFreeType2Autohinted) |
| 205 |
mImageDesc.image_type |= ftc_image_flag_autohinted; |
211 |
mLoadFlag |= FT_LOAD_FORCE_AUTOHINT; |
| 206 |
|
212 |
|
| 207 |
if (nsFreeType2::gFreeType2Unhinted) |
213 |
if (nsFreeType2::gFreeType2Unhinted) |
| 208 |
mImageDesc.image_type |= ftc_image_flag_unhinted; |
214 |
mLoadFlag |= FT_LOAD_NO_HINTING; |
| 209 |
|
215 |
|
| 210 |
PRUint32 num_embedded_bitmaps, i; |
216 |
PRUint32 num_embedded_bitmaps, i; |
| 211 |
PRInt32* embedded_bitmapheights; |
217 |
PRInt32* embedded_bitmapheights; |
|
Lines 218-224
Link Here
|
| 218 |
if (embedded_bitmapheights[i] == aPixelSize) { |
224 |
if (embedded_bitmapheights[i] == aPixelSize) { |
| 219 |
embedded_bimap = PR_TRUE; |
225 |
embedded_bimap = PR_TRUE; |
| 220 |
// unhinted must be set for embedded bitmaps to be used |
226 |
// unhinted must be set for embedded bitmaps to be used |
| 221 |
mImageDesc.image_type |= ftc_image_flag_unhinted; |
227 |
mLoadFlag |= FT_LOAD_NO_HINTING; |
| 222 |
break; |
228 |
break; |
| 223 |
} |
229 |
} |
| 224 |
} |
230 |
} |
|
Lines 230-235
Link Here
|
| 230 |
mFt2 = do_GetService(NS_FREETYPE2_CONTRACTID, &rv); |
236 |
mFt2 = do_GetService(NS_FREETYPE2_CONTRACTID, &rv); |
| 231 |
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to find FreeType routines"); |
237 |
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to find FreeType routines"); |
| 232 |
|
238 |
|
|
|
239 |
if (mFt2) { |
| 240 |
rv = mFt2->GetLibrary(&mFreeTypeLibrary); |
| 241 |
NS_ASSERTION(NS_SUCCEEDED(rv), "failed to find FreeType library"); |
| 242 |
} |
| 243 |
|
| 233 |
FREETYPE_FONT_PRINTF(("anti_alias=%d, embedded_bitmap=%d, " |
244 |
FREETYPE_FONT_PRINTF(("anti_alias=%d, embedded_bitmap=%d, " |
| 234 |
"AutoHinted=%d, gFreeType2Unhinted = %d, " |
245 |
"AutoHinted=%d, gFreeType2Unhinted = %d, " |
| 235 |
"size=%dpx, \"%s\"", |
246 |
"size=%dpx, \"%s\"", |
|
Lines 288-295
Link Here
|
| 288 |
PRInt32* aDescent, |
299 |
PRInt32* aDescent, |
| 289 |
PRInt32* aWidth) |
300 |
PRInt32* aWidth) |
| 290 |
{ |
301 |
{ |
| 291 |
nsresult rv; |
|
|
| 292 |
|
| 293 |
*aLeftBearing = 0; |
302 |
*aLeftBearing = 0; |
| 294 |
*aRightBearing = 0; |
303 |
*aRightBearing = 0; |
| 295 |
*aAscent = 0; |
304 |
*aAscent = 0; |
|
Lines 312-322
Link Here
|
| 312 |
if (!face) |
321 |
if (!face) |
| 313 |
return NS_ERROR_FAILURE; |
322 |
return NS_ERROR_FAILURE; |
| 314 |
|
323 |
|
| 315 |
FTC_Image_Cache icache; |
|
|
| 316 |
mFt2->GetImageCache(&icache); |
| 317 |
if (!icache) |
| 318 |
return NS_ERROR_FAILURE; |
| 319 |
|
| 320 |
// get the text size |
324 |
// get the text size |
| 321 |
PRUint32 i, extraSurrogateLength; |
325 |
PRUint32 i, extraSurrogateLength; |
| 322 |
for (i=0; i<aLength; i+=1+extraSurrogateLength) { |
326 |
for (i=0; i<aLength; i+=1+extraSurrogateLength) { |
|
Lines 337-352
Link Here
|
| 337 |
} |
341 |
} |
| 338 |
mFt2->GetCharIndex(face, code_point, &glyph_index); |
342 |
mFt2->GetCharIndex(face, code_point, &glyph_index); |
| 339 |
|
343 |
|
| 340 |
//NS_ASSERTION(glyph_index,"failed to get glyph"); |
344 |
// XXX : we need some caching here |
| 341 |
if (glyph_index) { |
345 |
if (glyph_index && |
| 342 |
rv = mFt2->ImageCacheLookup(icache, &mImageDesc, glyph_index, &glyph); |
346 |
NS_SUCCEEDED(mFt2->LoadGlyph(face, glyph_index, mLoadFlag)) && |
| 343 |
NS_ASSERTION(NS_SUCCEEDED(rv),"error loading glyph"); |
347 |
// NS_SUCCEEDED(mFt2->LoadGlyph(face, glyph_index, FT_LOAD_DEFAULT)) && |
| 344 |
} |
348 |
NS_SUCCEEDED(mFt2->GetGlyph(face->glyph, &glyph))) { |
| 345 |
if ((glyph_index) && (NS_SUCCEEDED(rv))) { |
|
|
| 346 |
mFt2->GlyphGetCBox(glyph, ft_glyph_bbox_pixels, &glyph_bbox); |
349 |
mFt2->GlyphGetCBox(glyph, ft_glyph_bbox_pixels, &glyph_bbox); |
| 347 |
advance = FT_16_16_TO_REG(glyph->advance.x); |
350 |
advance = FT_16_16_TO_REG(glyph->advance.x); |
|
|
351 |
mFt2->DoneGlyph(glyph); |
| 348 |
} |
352 |
} |
| 349 |
else { |
353 |
else { |
|
|
354 |
NS_ERROR("failed to get or load glyph"); |
| 350 |
// allocate space to draw an empty box in |
355 |
// allocate space to draw an empty box in |
| 351 |
GetFallbackGlyphMetrics(&glyph_bbox, face); |
356 |
GetFallbackGlyphMetrics(&glyph_bbox, face); |
| 352 |
advance = glyph_bbox.xMax + 1; |
357 |
advance = glyph_bbox.xMax + 1; |
|
Lines 401-411
Link Here
|
| 401 |
if (!face) |
406 |
if (!face) |
| 402 |
return 0; |
407 |
return 0; |
| 403 |
|
408 |
|
| 404 |
FTC_Image_Cache icache; |
|
|
| 405 |
mFt2->GetImageCache(&icache); |
| 406 |
if (!icache) |
| 407 |
return 0; |
| 408 |
|
| 409 |
PRUint32 i, extraSurrogateLength; |
409 |
PRUint32 i, extraSurrogateLength; |
| 410 |
for (i=0; i<aLength; i+=1+extraSurrogateLength) { |
410 |
for (i=0; i<aLength; i+=1+extraSurrogateLength) { |
| 411 |
extraSurrogateLength=0; |
411 |
extraSurrogateLength=0; |
|
Lines 418-432
Link Here
|
| 418 |
// skip aString[i+1], it is already used as low surrogate |
418 |
// skip aString[i+1], it is already used as low surrogate |
| 419 |
extraSurrogateLength = 1; |
419 |
extraSurrogateLength = 1; |
| 420 |
} |
420 |
} |
|
|
421 |
|
| 422 |
// XXX : we need some caching here |
| 421 |
mFt2->GetCharIndex((FT_Face)face, code_point, &glyph_index); |
423 |
mFt2->GetCharIndex((FT_Face)face, code_point, &glyph_index); |
| 422 |
nsresult rv; |
424 |
if (NS_FAILED(mFt2->LoadGlyph(face, glyph_index, mLoadFlag)) || |
| 423 |
rv = mFt2->ImageCacheLookup(icache, &mImageDesc, glyph_index, &glyph); |
425 |
// if (NS_FAILED(mFt2->LoadGlyph(face, glyph_index, FT_LOAD_DEFAULT)) || |
| 424 |
NS_ASSERTION(NS_SUCCEEDED(rv),"error loading glyph"); |
426 |
NS_FAILED(mFt2->GetGlyph(face->glyph, &glyph))) { |
| 425 |
if (NS_FAILED(rv)) { |
427 |
NS_ERROR("error loading glyph"); |
| 426 |
origin_x += face->size->metrics.x_ppem/2 + 2; |
428 |
origin_x += face->size->metrics.x_ppem/2 + 2; |
| 427 |
continue; |
429 |
continue; |
| 428 |
} |
430 |
} |
| 429 |
origin_x += FT_16_16_TO_REG(glyph->advance.x); |
431 |
origin_x += FT_16_16_TO_REG(glyph->advance.x); |
|
|
432 |
mFt2->DoneGlyph(glyph); |
| 430 |
} |
433 |
} |
| 431 |
|
434 |
|
| 432 |
return origin_x; |
435 |
return origin_x; |
|
Lines 723-733
Link Here
|
| 723 |
if (y%4==0) (*blendPixelFunc)(sub_image, y, ascent-1, black, 255/2); |
726 |
if (y%4==0) (*blendPixelFunc)(sub_image, y, ascent-1, black, 255/2); |
| 724 |
#endif |
727 |
#endif |
| 725 |
|
728 |
|
| 726 |
FTC_Image_Cache icache; |
|
|
| 727 |
mFt2->GetImageCache(&icache); |
| 728 |
if (!icache) |
| 729 |
return 0; |
| 730 |
|
| 731 |
// |
729 |
// |
| 732 |
// Get aa glyphs and blend with background |
730 |
// Get aa glyphs and blend with background |
| 733 |
// |
731 |
// |
|
Lines 736-742
Link Here
|
| 736 |
for (i=0; i<aLength; i+=1+extraSurrogateLength) { |
734 |
for (i=0; i<aLength; i+=1+extraSurrogateLength) { |
| 737 |
FT_UInt glyph_index; |
735 |
FT_UInt glyph_index; |
| 738 |
FT_Glyph glyph; |
736 |
FT_Glyph glyph; |
| 739 |
nsresult rv; |
|
|
| 740 |
FT_BBox glyph_bbox; |
737 |
FT_BBox glyph_bbox; |
| 741 |
FT_ULong code_point = aString[i]; |
738 |
FT_ULong code_point = aString[i]; |
| 742 |
extraSurrogateLength = 0; |
739 |
extraSurrogateLength = 0; |
|
Lines 750-760
Link Here
|
| 750 |
extraSurrogateLength = 1; |
747 |
extraSurrogateLength = 1; |
| 751 |
} |
748 |
} |
| 752 |
|
749 |
|
|
|
750 |
// XXX : we need some caching here |
| 753 |
mFt2->GetCharIndex(face, code_point, &glyph_index); |
751 |
mFt2->GetCharIndex(face, code_point, &glyph_index); |
| 754 |
if (glyph_index) { |
752 |
if (glyph_index && |
| 755 |
rv = mFt2->ImageCacheLookup(icache, &mImageDesc, glyph_index, &glyph); |
753 |
NS_SUCCEEDED(mFt2->LoadGlyph(face, glyph_index, mLoadFlag)) && |
| 756 |
} |
754 |
// NS_SUCCEEDED(mFt2->LoadGlyph(face, glyph_index, FT_LOAD_DEFAULT)) && |
| 757 |
if ((glyph_index) && (NS_SUCCEEDED(rv))) { |
755 |
NS_SUCCEEDED(mFt2->GetGlyph(face->glyph, &glyph))) { |
| 758 |
mFt2->GlyphGetCBox(glyph, ft_glyph_bbox_pixels, &glyph_bbox); |
756 |
mFt2->GlyphGetCBox(glyph, ft_glyph_bbox_pixels, &glyph_bbox); |
| 759 |
} |
757 |
} |
| 760 |
else { |
758 |
else { |
|
Lines 775-787
Link Here
|
| 775 |
continue; |
773 |
continue; |
| 776 |
} |
774 |
} |
| 777 |
|
775 |
|
| 778 |
FT_BitmapGlyph slot = (FT_BitmapGlyph)glyph; |
776 |
FT_BitmapGlyph slot; |
|
|
777 |
|
| 778 |
if (glyph->format != FT_GLYPH_FORMAT_BITMAP) |
| 779 |
{ |
| 780 |
if (mFt2->GlyphToBitmap(&glyph, FT_RENDER_MODE_NORMAL, 0, 1)) { |
| 781 |
NS_ERROR("failed to convert outline to bitmap "); |
| 782 |
XDestroyImage(sub_image); |
| 783 |
mFt2->DoneGlyph(glyph); |
| 784 |
return 0; |
| 785 |
} |
| 786 |
} |
| 787 |
|
| 788 |
slot = (FT_BitmapGlyph)glyph; |
| 779 |
nsAntiAliasedGlyph aaglyph(glyph_bbox.xMax-glyph_bbox.xMin, |
789 |
nsAntiAliasedGlyph aaglyph(glyph_bbox.xMax-glyph_bbox.xMin, |
| 780 |
glyph_bbox.yMax-glyph_bbox.yMin, 0); |
790 |
glyph_bbox.yMax-glyph_bbox.yMin, 0); |
| 781 |
PRUint8 buf[IMAGE_BUFFER_SIZE]; // try to use the stack for data |
791 |
PRUint8 buf[IMAGE_BUFFER_SIZE]; // try to use the stack for data |
| 782 |
if (!aaglyph.WrapFreeType(&glyph_bbox, slot, buf, IMAGE_BUFFER_SIZE)) { |
792 |
if (!aaglyph.WrapFreeType(&glyph_bbox, slot, buf, IMAGE_BUFFER_SIZE)) { |
| 783 |
NS_ERROR("failed to wrap freetype image"); |
793 |
NS_ERROR("failed to wrap freetype image"); |
| 784 |
XDestroyImage(sub_image); |
794 |
XDestroyImage(sub_image); |
|
|
795 |
mFt2->DoneGlyph(glyph); |
| 785 |
return 0; |
796 |
return 0; |
| 786 |
} |
797 |
} |
| 787 |
|
798 |
|
|
Lines 815-820
Link Here
|
| 815 |
x_pos + aaglyph.GetLBearing(), ascent-glyph_bbox.yMax); |
826 |
x_pos + aaglyph.GetLBearing(), ascent-glyph_bbox.yMax); |
| 816 |
|
827 |
|
| 817 |
x_pos += aaglyph.GetAdvance(); |
828 |
x_pos += aaglyph.GetAdvance(); |
|
|
829 |
mFt2->DoneGlyph(glyph); |
| 818 |
} |
830 |
} |
| 819 |
|
831 |
|
| 820 |
// |
832 |
// |