@@ -130,8 +130,7 @@ public: | |||
if (rowIsSelected) | |||
g.fillAll (Colours::lightblue); | |||
Font font (fonts [rowNumber]); | |||
font.setHeight (height * 0.7f); | |||
Font font = fonts[rowNumber].withPointHeight (height * 0.6f); | |||
g.setFont (font); | |||
g.setColour (Colours::black); | |||
@@ -304,15 +304,9 @@ bool CustomTypeface::writeToStream (OutputStream& outputStream) | |||
} | |||
//============================================================================== | |||
float CustomTypeface::getAscent() const | |||
{ | |||
return ascent; | |||
} | |||
float CustomTypeface::getDescent() const | |||
{ | |||
return 1.0f - ascent; | |||
} | |||
float CustomTypeface::getAscent() const { return ascent; } | |||
float CustomTypeface::getDescent() const { return 1.0f - ascent; } | |||
float CustomTypeface::getHeightToPointsFactor() const { return ascent; } | |||
float CustomTypeface::getStringWidth (const String& text) | |||
{ | |||
@@ -120,6 +120,7 @@ public: | |||
// The following methods implement the basic Typeface behaviour. | |||
float getAscent() const; | |||
float getDescent() const; | |||
float getHeightToPointsFactor() const; | |||
float getStringWidth (const String& text); | |||
void getGlyphPositions (const String& text, Array <int>& glyphs, Array<float>& xOffsets); | |||
bool getOutlineForGlyph (int glyphNumber, Path& path); | |||
@@ -446,6 +446,13 @@ Font Font::withHeight (const float newHeight) const | |||
return f; | |||
} | |||
Font Font::withPointHeight (float heightInPoints) const | |||
{ | |||
Font f (*this); | |||
f.setHeight (heightInPoints / getTypeface()->getHeightToPointsFactor()); | |||
return f; | |||
} | |||
void Font::setHeight (float newHeight) | |||
{ | |||
newHeight = FontValues::limitFontHeight (newHeight); | |||
@@ -215,6 +215,9 @@ public: | |||
/** Returns a copy of this font with a new height. */ | |||
Font withHeight (float height) const; | |||
/** Returns a copy of this font with a new height, specified in points. */ | |||
Font withPointHeight (float heightInPoints) const; | |||
/** Changes the font's height. | |||
@see getHeight, withHeight, setHeightWithoutChangingWidth | |||
*/ | |||
@@ -94,24 +94,24 @@ public: | |||
*/ | |||
virtual float getDescent() const = 0; | |||
/** Measures the width of a line of text. | |||
/** Returns the value by which you should multiply a juce font-height value to | |||
convert it to the equivalent point-size. | |||
*/ | |||
virtual float getHeightToPointsFactor() const = 0; | |||
/** Measures the width of a line of text. | |||
The distance returned is based on the font having an normalised height of 1.0. | |||
You should never need to call this directly! Use Font::getStringWidth() instead! | |||
*/ | |||
virtual float getStringWidth (const String& text) = 0; | |||
/** Converts a line of text into its glyph numbers and their positions. | |||
The distances returned are based on the font having an normalised height of 1.0. | |||
You should never need to call this directly! Use Font::getGlyphPositions() instead! | |||
*/ | |||
virtual void getGlyphPositions (const String& text, Array <int>& glyphs, Array<float>& xOffsets) = 0; | |||
/** Returns the outline for a glyph. | |||
The path returned will be normalised to a font height of 1.0. | |||
*/ | |||
virtual bool getOutlineForGlyph (int glyphNumber, Path& path) = 0; | |||
@@ -89,14 +89,16 @@ Typeface::Ptr Font::getDefaultTypefaceForFont (const Font& font) | |||
return Typeface::createSystemTypefaceFor (f); | |||
} | |||
const float referenceFontSize = 256.0f; | |||
const float referenceFontToUnits = 1.0f / referenceFontSize; | |||
//============================================================================== | |||
class AndroidTypeface : public Typeface | |||
{ | |||
public: | |||
AndroidTypeface (const Font& font) | |||
: Typeface (font.getTypefaceName(), font.getTypefaceStyle()), | |||
ascent (0), | |||
descent (0) | |||
ascent (0), descent (0), heightToPointsFactor (1.0f) | |||
{ | |||
JNIEnv* const env = getEnv(); | |||
@@ -121,17 +123,20 @@ public: | |||
paint = GlobalRef (GraphicsHelpers::createPaint (Graphics::highResamplingQuality)); | |||
const LocalRef<jobject> ignored (paint.callObjectMethod (Paint.setTypeface, typeface.get())); | |||
const float standardSize = 256.0f; | |||
paint.callVoidMethod (Paint.setTextSize, standardSize); | |||
ascent = std::abs (paint.callFloatMethod (Paint.ascent)) / standardSize; | |||
descent = paint.callFloatMethod (Paint.descent) / standardSize; | |||
paint.callVoidMethod (Paint.setTextSize, referenceFontSize); | |||
const float fullAscent = std::abs (paint.callFloatMethod (Paint.ascent)); | |||
const float fullDescent = paint.callFloatMethod (Paint.descent); | |||
const float totalHeight = fullAscent + fullDescent; | |||
const float height = ascent + descent; | |||
unitsToHeightScaleFactor = 1.0f / 256.0f; | |||
ascent = fullAscent / totalHeight; | |||
descent = fullDescent / totalHeight; | |||
heightToPointsFactor = referenceFontSize / totalHeight; | |||
} | |||
float getAscent() const { return ascent; } | |||
float getDescent() const { return descent; } | |||
float getAscent() const { return ascent; } | |||
float getDescent() const { return descent; } | |||
float getHeightToPointsFactor() const { return heightToPointsFactor; } | |||
float getStringWidth (const String& text) | |||
{ | |||
@@ -149,7 +154,7 @@ public: | |||
for (int i = 0; i < numDone; ++i) | |||
x += localWidths[i]; | |||
return x * unitsToHeightScaleFactor; | |||
return x * referenceFontToUnits; | |||
} | |||
void getGlyphPositions (const String& text, Array<int>& glyphs, Array<float>& xOffsets) | |||
@@ -173,7 +178,7 @@ public: | |||
{ | |||
glyphs.add ((int) s.getAndAdvance()); | |||
x += localWidths[i]; | |||
xOffsets.add (x * unitsToHeightScaleFactor); | |||
xOffsets.add (x * referenceFontToUnits); | |||
} | |||
} | |||
@@ -186,7 +191,7 @@ public: | |||
{ | |||
JNIEnv* env = getEnv(); | |||
jobject matrix = GraphicsHelpers::createMatrix (env, AffineTransform::scale (unitsToHeightScaleFactor).followedBy (t)); | |||
jobject matrix = GraphicsHelpers::createMatrix (env, AffineTransform::scale (referenceFontToUnits).followedBy (t)); | |||
jintArray maskData = (jintArray) android.activity.callObjectMethod (JuceAppActivity.renderGlyph, (jchar) glyphNumber, paint.get(), matrix, rect.get()); | |||
env->DeleteLocalRef (matrix); | |||
@@ -227,7 +232,7 @@ public: | |||
} | |||
GlobalRef typeface, paint, rect; | |||
float ascent, descent, unitsToHeightScaleFactor; | |||
float ascent, descent, heightToPointsFactor; | |||
private: | |||
static File findFontFile (const String& family, | |||
@@ -561,7 +561,7 @@ void CoreGraphicsContext::setFont (const Font& newFont) | |||
{ | |||
state->fontRef = osxTypeface->fontRef; | |||
CGContextSetFont (context, state->fontRef); | |||
CGContextSetFontSize (context, state->font.getHeight() * osxTypeface->fontHeightToCGSizeFactor); | |||
CGContextSetFontSize (context, state->font.getHeight() * osxTypeface->fontHeightToPointsFactor); | |||
state->fontTransform = osxTypeface->renderingTransform; | |||
state->fontTransform.a *= state->font.getHorizontalScale(); | |||
@@ -28,6 +28,8 @@ | |||
#define JUCE_CORETEXT_AVAILABLE 1 | |||
#endif | |||
const float referenceFontSize = 1024.0f; | |||
#if JUCE_CORETEXT_AVAILABLE | |||
#if JUCE_MAC && MAC_OS_X_VERSION_MAX_ALLOWED == MAC_OS_X_VERSION_10_5 | |||
@@ -70,14 +72,14 @@ namespace CoreTextTypeLayout | |||
} | |||
static CTFontRef useStyleFallbackIfNecessary (CTFontRef ctFontRef, CFStringRef cfFontFamily, | |||
const float fontSize, const Font& font) | |||
const float fontSizePoints, const Font& font) | |||
{ | |||
CFStringRef cfActualFontFamily = (CFStringRef) CTFontCopyAttribute (ctFontRef, kCTFontFamilyNameAttribute); | |||
if (CFStringCompare (cfFontFamily, cfActualFontFamily, 0) != kCFCompareEqualTo) | |||
{ | |||
CFRelease (ctFontRef); | |||
ctFontRef = CTFontCreateWithName (cfFontFamily, fontSize, nullptr); | |||
ctFontRef = CTFontCreateWithName (cfFontFamily, fontSizePoints, nullptr); | |||
if (font.isItalic()) ctFontRef = getFontWithTrait (ctFontRef, kCTFontItalicTrait); | |||
if (font.isBold()) ctFontRef = getFontWithTrait (ctFontRef, kCTFontBoldTrait); | |||
@@ -88,8 +90,24 @@ namespace CoreTextTypeLayout | |||
} | |||
#endif | |||
static CTFontRef createCTFont (const Font& font, const float fontSize, | |||
CGAffineTransform& transformRequired, const bool applyScaleFactor) | |||
static float getFontTotalHeight (CTFontRef font) | |||
{ | |||
return std::abs ((float) CTFontGetAscent (font)) + std::abs ((float) CTFontGetDescent (font)); | |||
} | |||
static float getHeightToPointsFactor (CTFontRef font) | |||
{ | |||
return referenceFontSize / getFontTotalHeight (font); | |||
} | |||
static CTFontRef getFontWithPointSize (CTFontRef font, float size) | |||
{ | |||
CTFontRef newFont = CTFontCreateCopyWithAttributes (font, size, nullptr, nullptr); | |||
CFRelease (font); | |||
return newFont; | |||
} | |||
static CTFontRef createCTFont (const Font& font, const float fontSizePoints, CGAffineTransform& transformRequired) | |||
{ | |||
CFStringRef cfFontFamily = FontStyleHelpers::getConcreteFamilyName (font).toCFString(); | |||
CFStringRef cfFontStyle = findBestAvailableStyle (font, transformRequired).toCFString(); | |||
@@ -106,27 +124,15 @@ namespace CoreTextTypeLayout | |||
CTFontDescriptorRef ctFontDescRef = CTFontDescriptorCreateWithAttributes (fontDescAttributes); | |||
CFRelease (fontDescAttributes); | |||
CTFontRef ctFontRef = CTFontCreateWithFontDescriptor (ctFontDescRef, fontSize, nullptr); | |||
CTFontRef ctFontRef = CTFontCreateWithFontDescriptor (ctFontDescRef, fontSizePoints, nullptr); | |||
CFRelease (ctFontDescRef); | |||
#if JUCE_MAC && ((! defined (MAC_OS_X_VERSION_10_7)) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7) | |||
ctFontRef = useStyleFallbackIfNecessary (ctFontRef, cfFontFamily, fontSize, font); | |||
ctFontRef = useStyleFallbackIfNecessary (ctFontRef, cfFontFamily, fontSizePoints, font); | |||
#endif | |||
CFRelease (cfFontFamily); | |||
if (applyScaleFactor) | |||
{ | |||
CGFontRef cgFontRef = CTFontCopyGraphicsFont (ctFontRef, nullptr); | |||
const int totalHeight = std::abs (CGFontGetAscent (cgFontRef)) + std::abs (CGFontGetDescent (cgFontRef)); | |||
const float factor = CGFontGetUnitsPerEm (cgFontRef) / (float) totalHeight; | |||
CGFontRelease (cgFontRef); | |||
CTFontRef newFont = CTFontCreateCopyWithAttributes (ctFontRef, fontSize * factor, nullptr, nullptr); | |||
CFRelease (ctFontRef); | |||
ctFontRef = newFont; | |||
} | |||
return ctFontRef; | |||
} | |||
@@ -209,7 +215,8 @@ namespace CoreTextTypeLayout | |||
if (const Font* const f = attr->getFont()) | |||
{ | |||
CGAffineTransform transform; | |||
CTFontRef ctFontRef = createCTFont (*f, f->getHeight(), transform, true); | |||
CTFontRef ctFontRef = createCTFont (*f, referenceFontSize, transform); | |||
ctFontRef = getFontWithPointSize (ctFontRef, f->getHeight() * getHeightToPointsFactor (ctFontRef)); | |||
CFAttributedStringSetAttribute (attribString, CFRangeMake (range.getStart(), range.getLength()), | |||
kCTFontAttributeName, ctFontRef); | |||
@@ -362,21 +369,18 @@ namespace CoreTextTypeLayout | |||
if (CFDictionaryGetValueIfPresent (runAttributes, kCTFontAttributeName, (const void **) &ctRunFont)) | |||
{ | |||
CFStringRef cfsFontName = CTFontCopyPostScriptName (ctRunFont); | |||
CTFontRef ctFontRef = CTFontCreateWithName (cfsFontName, 1024, nullptr); | |||
CTFontRef ctFontRef = CTFontCreateWithName (cfsFontName, referenceFontSize, nullptr); | |||
CFRelease (cfsFontName); | |||
CGFontRef cgFontRef = CTFontCopyGraphicsFont (ctFontRef, nullptr); | |||
const float fontHeightToPointsFactor = getHeightToPointsFactor (ctFontRef); | |||
CFRelease (ctFontRef); | |||
const int totalHeight = std::abs (CGFontGetAscent (cgFontRef)) + std::abs (CGFontGetDescent (cgFontRef)); | |||
const float fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (cgFontRef) / (float) totalHeight; | |||
CGFontRelease (cgFontRef); | |||
CFStringRef cfsFontFamily = (CFStringRef) CTFontCopyAttribute (ctRunFont, kCTFontFamilyNameAttribute); | |||
CFStringRef cfsFontStyle = (CFStringRef) CTFontCopyAttribute (ctRunFont, kCTFontStyleNameAttribute); | |||
glyphRun->font = Font (String::fromCFString (cfsFontFamily), | |||
String::fromCFString (cfsFontStyle), | |||
CTFontGetSize (ctRunFont) / fontHeightToCGSizeFactor); | |||
CTFontGetSize (ctRunFont) / fontHeightToPointsFactor); | |||
CFRelease (cfsFontStyle); | |||
CFRelease (cfsFontFamily); | |||
@@ -415,29 +419,27 @@ public: | |||
: Typeface (font.getTypefaceName(), | |||
font.getTypefaceStyle()), | |||
fontRef (nullptr), | |||
fontHeightToCGSizeFactor (1.0f), | |||
fontHeightToPointsFactor (1.0f), | |||
renderingTransform (CGAffineTransformIdentity), | |||
ctFontRef (nullptr), | |||
attributedStringAtts (nullptr), | |||
ascent (0.0f), | |||
unitsToHeightScaleFactor (0.0f) | |||
{ | |||
ctFontRef = CoreTextTypeLayout::createCTFont (font, 1024.0f, renderingTransform, false); | |||
ctFontRef = CoreTextTypeLayout::createCTFont (font, referenceFontSize, renderingTransform); | |||
if (ctFontRef != nullptr) | |||
{ | |||
ascent = std::abs ((float) CTFontGetAscent (ctFontRef)); | |||
const float totalSize = ascent + std::abs ((float) CTFontGetDescent (ctFontRef)); | |||
ascent /= totalSize; | |||
const float ctAscent = std::abs ((float) CTFontGetAscent (ctFontRef)); | |||
const float ctDescent = std::abs ((float) CTFontGetDescent (ctFontRef)); | |||
const float ctTotalHeight = ctAscent + ctDescent; | |||
pathTransform = AffineTransform::identity.scale (1.0f / totalSize); | |||
ascent = ctAscent / ctTotalHeight; | |||
unitsToHeightScaleFactor = 1.0f / ctTotalHeight; | |||
pathTransform = AffineTransform::identity.scale (unitsToHeightScaleFactor); | |||
fontRef = CTFontCopyGraphicsFont (ctFontRef, nullptr); | |||
const int totalHeight = std::abs (CGFontGetAscent (fontRef)) + std::abs (CGFontGetDescent (fontRef)); | |||
const float ctTotalHeight = std::abs (CTFontGetAscent (ctFontRef)) + std::abs (CTFontGetDescent (ctFontRef)); | |||
unitsToHeightScaleFactor = 1.0f / ctTotalHeight; | |||
fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / (float) totalHeight; | |||
fontHeightToPointsFactor = referenceFontSize / ctTotalHeight; | |||
const short zero = 0; | |||
CFNumberRef numberRef = CFNumberCreate (0, kCFNumberShortType, &zero); | |||
@@ -462,8 +464,9 @@ public: | |||
CFRelease (ctFontRef); | |||
} | |||
float getAscent() const { return ascent; } | |||
float getDescent() const { return 1.0f - ascent; } | |||
float getAscent() const { return ascent; } | |||
float getDescent() const { return 1.0f - ascent; } | |||
float getHeightToPointsFactor() const { return fontHeightToPointsFactor; } | |||
float getStringWidth (const String& text) | |||
{ | |||
@@ -565,7 +568,7 @@ public: | |||
//============================================================================== | |||
CGFontRef fontRef; | |||
float fontHeightToCGSizeFactor; | |||
float fontHeightToPointsFactor; | |||
CGAffineTransform renderingTransform; | |||
private: | |||
@@ -717,7 +720,7 @@ public: | |||
juceStringToNS (style), NSFontFaceAttribute, nil]; | |||
NSFontDescriptor* nsFontDesc = [NSFontDescriptor fontDescriptorWithFontAttributes: nsDict]; | |||
nsFont = [NSFont fontWithDescriptor: nsFontDesc size: 1024]; | |||
nsFont = [NSFont fontWithDescriptor: nsFontDesc size: referenceFontSize]; | |||
[nsFont retain]; | |||
@@ -737,7 +740,7 @@ public: | |||
const float totalHeight = std::abs ([nsFont ascender]) + std::abs ([nsFont descender]); | |||
unitsToHeightScaleFactor = 1.0f / totalHeight; | |||
fontHeightToCGSizeFactor = 1024.0f / totalHeight; | |||
fontHeightToPointsFactor = referenceFontSize / totalHeight; | |||
#else | |||
#if SUPPORT_10_4_FONTS | |||
if (NEW_CGFONT_FUNCTIONS_UNAVAILABLE) | |||
@@ -751,16 +754,15 @@ public: | |||
const float totalHeight = std::abs ([nsFont ascender]) + std::abs ([nsFont descender]); | |||
unitsToHeightScaleFactor = 1.0f / totalHeight; | |||
fontHeightToCGSizeFactor = 1024.0f / totalHeight; | |||
fontHeightToPointsFactor = referenceFontSize / totalHeight; | |||
} | |||
else | |||
#endif | |||
{ | |||
fontRef = CGFontCreateWithFontName ((CFStringRef) [nsFont fontName]); | |||
const int totalHeight = abs (CGFontGetAscent (fontRef)) + abs (CGFontGetDescent (fontRef)); | |||
unitsToHeightScaleFactor = 1.0f / totalHeight; | |||
fontHeightToCGSizeFactor = CGFontGetUnitsPerEm (fontRef) / (float) totalHeight; | |||
unitsToHeightScaleFactor = 1.0f / getFontTotalHeight (fontRef); | |||
fontHeightToPointsFactor = getHeightToPointsFactor (fontRef); | |||
} | |||
#endif | |||
} | |||
@@ -775,8 +777,9 @@ public: | |||
CGFontRelease (fontRef); | |||
} | |||
float getAscent() const { return ascent; } | |||
float getDescent() const { return 1.0f - ascent; } | |||
float getAscent() const { return ascent; } | |||
float getDescent() const { return 1.0f - ascent; } | |||
float getHeightToPointsFactor() const { return fontHeightToPointsFactor; } | |||
float getStringWidth (const String& text) | |||
{ | |||
@@ -928,7 +931,7 @@ public: | |||
//============================================================================== | |||
CGFontRef fontRef; | |||
float fontHeightToCGSizeFactor; | |||
float fontHeightToPointsFactor; | |||
CGAffineTransform renderingTransform; | |||
private: | |||
@@ -547,7 +547,7 @@ public: | |||
{ | |||
WindowsDirectWriteTypeface* typeface = dynamic_cast<WindowsDirectWriteTypeface*> (font.getTypeface()); | |||
currentFontFace = typeface->getIDWriteFontFace(); | |||
fontHeightToEmSizeFactor = typeface->getFontHeightToEmSizeFactor(); | |||
fontHeightToEmSizeFactor = typeface->unitsToHeightScaleFactor(); | |||
} | |||
} | |||
@@ -160,7 +160,7 @@ namespace DirectWriteTypeLayout | |||
}; | |||
//================================================================================================== | |||
float getFontHeightToEmSizeFactor (IDWriteFont* const dwFont) | |||
static float getFontHeightToEmSizeFactor (IDWriteFont* const dwFont) | |||
{ | |||
ComSmartPtr<IDWriteFontFace> dwFontFace; | |||
dwFont->CreateFontFace (dwFontFace.resetAndGetPointerAddress()); | |||
@@ -181,8 +181,9 @@ public: | |||
pathTransform = AffineTransform::scale (pathScale); | |||
} | |||
float getAscent() const { return ascent; } | |||
float getDescent() const { return 1.0f - ascent; } | |||
float getAscent() const { return ascent; } | |||
float getDescent() const { return 1.0f - ascent; } | |||
float getHeightToPointsFactor() const { return unitsToHeightScaleFactor; } | |||
float getStringWidth (const String& text) | |||
{ | |||
@@ -250,7 +251,6 @@ public: | |||
} | |||
IDWriteFontFace* getIDWriteFontFace() const noexcept { return dwFontFace; } | |||
float getFontHeightToEmSizeFactor() const noexcept { return unitsToHeightScaleFactor; } | |||
private: | |||
ComSmartPtr<IDWriteFontFace> dwFontFace; | |||
@@ -210,13 +210,14 @@ public: | |||
fontH (0), | |||
previousFontH (0), | |||
dc (CreateCompatibleDC (0)), | |||
ascent (1.0f), | |||
ascent (1.0f), heightToPointsFactor (1.0f), | |||
defaultGlyph (-1) | |||
{ | |||
loadFont(); | |||
if (GetTextMetrics (dc, &tm)) | |||
{ | |||
heightToPointsFactor = 256.0f / tm.tmHeight; | |||
ascent = tm.tmAscent / (float) tm.tmHeight; | |||
defaultGlyph = getGlyphForChar (dc, tm.tmDefaultChar); | |||
createKerningPairs (dc, (float) tm.tmHeight); | |||
@@ -232,8 +233,9 @@ public: | |||
DeleteObject (fontH); | |||
} | |||
float getAscent() const { return ascent; } | |||
float getDescent() const { return 1.0f - ascent; } | |||
float getAscent() const { return ascent; } | |||
float getDescent() const { return 1.0f - ascent; } | |||
float getHeightToPointsFactor() const { return heightToPointsFactor; } | |||
float getStringWidth (const String& text) | |||
{ | |||
@@ -352,7 +354,7 @@ private: | |||
HGDIOBJ previousFontH; | |||
HDC dc; | |||
TEXTMETRIC tm; | |||
float ascent; | |||
float ascent, heightToPointsFactor; | |||
int defaultGlyph; | |||
struct KerningPair | |||
@@ -492,7 +494,7 @@ Typeface::Ptr Typeface::createSystemTypefaceFor (const Font& font) | |||
if (factories.systemFonts != nullptr) | |||
return new WindowsDirectWriteTypeface (font, factories.systemFonts); | |||
else | |||
#endif | |||
return new WindowsTypeface (font); | |||
return new WindowsTypeface (font); | |||
} |