mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-20 01:14:20 +00:00
CodeEditorComponent rendering improvements. Faster OSX font lookup.
This commit is contained in:
parent
a7b0ec0678
commit
4b128378cf
9 changed files with 75 additions and 70 deletions
|
|
@ -567,7 +567,7 @@ static void createTabTextLayout (const TabBarButton& button, const Rectangle<int
|
|||
textLayout.createLayout (s, (float) textArea.getWidth());
|
||||
}
|
||||
|
||||
static Colour getTabBackgroundColour (TabBarButton& button)
|
||||
Colour IntrojucerLookAndFeel::getTabBackgroundColour (TabBarButton& button)
|
||||
{
|
||||
const Colour bkg (button.findColour (mainBackgroundColourId).contrasting (0.15f));
|
||||
|
||||
|
|
@ -580,6 +580,7 @@ static Colour getTabBackgroundColour (TabBarButton& button)
|
|||
void IntrojucerLookAndFeel::drawTabButton (TabBarButton& button, Graphics& g, bool isMouseOver, bool isMouseDown)
|
||||
{
|
||||
const Rectangle<int> activeArea (button.getActiveArea());
|
||||
|
||||
const Colour bkg (getTabBackgroundColour (button));
|
||||
|
||||
g.setGradientFill (ColourGradient (bkg.brighter (0.1f), 0, (float) activeArea.getY(),
|
||||
|
|
|
|||
|
|
@ -89,6 +89,7 @@ public:
|
|||
int getTabButtonOverlap (int tabDepth);
|
||||
int getTabButtonSpaceAroundImage();
|
||||
int getTabButtonBestWidth (TabBarButton& button, int tabDepth);
|
||||
static Colour getTabBackgroundColour (TabBarButton& button);
|
||||
void drawTabButton (TabBarButton& button, Graphics& g, bool isMouseOver, bool isMouseDown);
|
||||
|
||||
Rectangle<int> getTabButtonExtraComponentBounds (const TabBarButton& button, Rectangle<int>& textArea, Component& comp);
|
||||
|
|
|
|||
|
|
@ -46,8 +46,7 @@ CodeDocument& SourceCodeDocument::getCodeDocument()
|
|||
|
||||
Component* SourceCodeDocument::createEditor()
|
||||
{
|
||||
SourceCodeEditor* e = new SourceCodeEditor (this);
|
||||
e->createEditor (getCodeDocument());
|
||||
SourceCodeEditor* e = new SourceCodeEditor (this, getCodeDocument());
|
||||
applyLastState (*(e->editor));
|
||||
return e;
|
||||
}
|
||||
|
|
@ -114,9 +113,21 @@ void SourceCodeDocument::applyLastState (CodeEditorComponent& editor) const
|
|||
}
|
||||
|
||||
//==============================================================================
|
||||
SourceCodeEditor::SourceCodeEditor (OpenDocumentManager::Document* doc)
|
||||
SourceCodeEditor::SourceCodeEditor (OpenDocumentManager::Document* doc, CodeDocument& codeDocument)
|
||||
: DocumentEditorComponent (doc)
|
||||
{
|
||||
setOpaque (true);
|
||||
|
||||
if (document->getFile().hasFileExtension (sourceOrHeaderFileExtensions))
|
||||
setEditor (new CppCodeEditorComponent (document->getFile(), codeDocument));
|
||||
else
|
||||
setEditor (new GenericCodeEditorComponent (document->getFile(), codeDocument, nullptr));
|
||||
}
|
||||
|
||||
SourceCodeEditor::SourceCodeEditor (OpenDocumentManager::Document* doc, CodeEditorComponent* ed)
|
||||
: DocumentEditorComponent (doc)
|
||||
{
|
||||
setEditor (ed);
|
||||
}
|
||||
|
||||
SourceCodeEditor::~SourceCodeEditor()
|
||||
|
|
@ -130,14 +141,6 @@ SourceCodeEditor::~SourceCodeEditor()
|
|||
doc->updateLastState (*editor);
|
||||
}
|
||||
|
||||
void SourceCodeEditor::createEditor (CodeDocument& codeDocument)
|
||||
{
|
||||
if (document->getFile().hasFileExtension (sourceOrHeaderFileExtensions))
|
||||
setEditor (new CppCodeEditorComponent (document->getFile(), codeDocument));
|
||||
else
|
||||
setEditor (new GenericCodeEditorComponent (document->getFile(), codeDocument, nullptr));
|
||||
}
|
||||
|
||||
void SourceCodeEditor::setEditor (CodeEditorComponent* newEditor)
|
||||
{
|
||||
if (editor != nullptr)
|
||||
|
|
|
|||
|
|
@ -141,12 +141,10 @@ class SourceCodeEditor : public DocumentEditorComponent,
|
|||
private CodeDocument::Listener
|
||||
{
|
||||
public:
|
||||
SourceCodeEditor (OpenDocumentManager::Document* document);
|
||||
SourceCodeEditor (OpenDocumentManager::Document* document, CodeDocument&);
|
||||
SourceCodeEditor (OpenDocumentManager::Document* document, CodeEditorComponent*);
|
||||
~SourceCodeEditor();
|
||||
|
||||
void createEditor (CodeDocument& codeDocument);
|
||||
void setEditor (CodeEditorComponent*);
|
||||
|
||||
void scrollToKeepRangeOnScreen (Range<int> range);
|
||||
void highlight (Range<int> range, bool cursorAtStart);
|
||||
|
||||
|
|
@ -165,6 +163,7 @@ private:
|
|||
void codeDocumentTextInserted (const String&, int);
|
||||
void codeDocumentTextDeleted (int, int);
|
||||
|
||||
void setEditor (CodeEditorComponent*);
|
||||
void updateColourScheme();
|
||||
void checkSaveState();
|
||||
|
||||
|
|
|
|||
|
|
@ -329,9 +329,9 @@ JucerDocumentEditor::JucerDocumentEditor (JucerDocument* const doc)
|
|||
|
||||
tabbedComponent.addTab ("Resources", tabColour, new ResourceEditorPanel (*document), true);
|
||||
|
||||
SourceCodeEditor* codeEditor = new SourceCodeEditor (&document->getCppDocument());
|
||||
codeEditor->setEditor (new CppCodeEditorComponent (document->getCppFile(),
|
||||
document->getCppDocument().getCodeDocument()));
|
||||
SourceCodeEditor* codeEditor = new SourceCodeEditor (&document->getCppDocument(),
|
||||
new CppCodeEditorComponent (document->getCppFile(),
|
||||
document->getCppDocument().getCodeDocument()));
|
||||
|
||||
tabbedComponent.addTab ("Code", tabColour, codeEditor, true);
|
||||
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ extern "C"
|
|||
}
|
||||
#endif
|
||||
|
||||
static CTFontRef getCTFontFromTypeface (const Font& f);
|
||||
|
||||
namespace CoreTextTypeLayout
|
||||
{
|
||||
static String findBestAvailableStyle (const Font& font, CGAffineTransform& requiredTransform)
|
||||
|
|
@ -187,6 +189,18 @@ namespace CoreTextTypeLayout
|
|||
HeapBlock<CGPoint> local;
|
||||
};
|
||||
|
||||
static CTFontRef getOrCreateFont (const Font& f)
|
||||
{
|
||||
if (CTFontRef ctf = getCTFontFromTypeface (f))
|
||||
{
|
||||
CFRetain (ctf);
|
||||
return ctf;
|
||||
}
|
||||
|
||||
CGAffineTransform transform;
|
||||
return createCTFont (f, referenceFontSize, transform);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static CFAttributedStringRef createCFAttributedString (const AttributedString& text)
|
||||
{
|
||||
|
|
@ -213,13 +227,14 @@ namespace CoreTextTypeLayout
|
|||
|
||||
if (const Font* const f = attr->getFont())
|
||||
{
|
||||
CGAffineTransform transform;
|
||||
CTFontRef ctFontRef = createCTFont (*f, referenceFontSize, transform);
|
||||
ctFontRef = getFontWithPointSize (ctFontRef, f->getHeight() * getHeightToPointsFactor (ctFontRef));
|
||||
if (CTFontRef ctFontRef = getOrCreateFont (*f))
|
||||
{
|
||||
ctFontRef = getFontWithPointSize (ctFontRef, f->getHeight() * getHeightToPointsFactor (ctFontRef));
|
||||
|
||||
CFAttributedStringSetAttribute (attribString, CFRangeMake (range.getStart(), range.getLength()),
|
||||
kCTFontAttributeName, ctFontRef);
|
||||
CFRelease (ctFontRef);
|
||||
CFAttributedStringSetAttribute (attribString, CFRangeMake (range.getStart(), range.getLength()),
|
||||
kCTFontAttributeName, ctFontRef);
|
||||
CFRelease (ctFontRef);
|
||||
}
|
||||
}
|
||||
|
||||
if (const Colour* const col = attr->getColour())
|
||||
|
|
@ -416,11 +431,11 @@ class OSXTypeface : public Typeface
|
|||
public:
|
||||
OSXTypeface (const Font& font)
|
||||
: Typeface (font.getTypefaceName(),
|
||||
font.getTypefaceStyle()),
|
||||
font.getTypefaceStyle()),
|
||||
fontRef (nullptr),
|
||||
ctFontRef (nullptr),
|
||||
fontHeightToPointsFactor (1.0f),
|
||||
renderingTransform (CGAffineTransformIdentity),
|
||||
ctFontRef (nullptr),
|
||||
attributedStringAtts (nullptr),
|
||||
ascent (0.0f),
|
||||
unitsToHeightScaleFactor (0.0f)
|
||||
|
|
@ -566,12 +581,12 @@ public:
|
|||
|
||||
//==============================================================================
|
||||
CGFontRef fontRef;
|
||||
CTFontRef ctFontRef;
|
||||
|
||||
float fontHeightToPointsFactor;
|
||||
CGAffineTransform renderingTransform;
|
||||
|
||||
private:
|
||||
CTFontRef ctFontRef;
|
||||
CFDictionaryRef attributedStringAtts;
|
||||
float ascent, unitsToHeightScaleFactor;
|
||||
AffineTransform pathTransform;
|
||||
|
|
@ -598,6 +613,15 @@ private:
|
|||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OSXTypeface)
|
||||
};
|
||||
|
||||
CTFontRef getCTFontFromTypeface (const Font& f)
|
||||
{
|
||||
if (OSXTypeface* tf = dynamic_cast <OSXTypeface*> (f.getTypeface()))
|
||||
return tf->ctFontRef;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
StringArray Font::findAllTypefaceNames()
|
||||
{
|
||||
StringArray names;
|
||||
|
|
|
|||
|
|
@ -158,28 +158,21 @@ void DrawableText::recalculateCoordinates (Expression::Scope* scope)
|
|||
repaint();
|
||||
}
|
||||
|
||||
const AffineTransform DrawableText::getArrangementAndTransform (GlyphArrangement& glyphs) const
|
||||
{
|
||||
const float w = Line<float> (resolvedPoints[0], resolvedPoints[1]).getLength();
|
||||
const float h = Line<float> (resolvedPoints[0], resolvedPoints[2]).getLength();
|
||||
|
||||
glyphs.addFittedText (scaledFont, text, 0, 0, w, h, justification, 0x100000);
|
||||
|
||||
return AffineTransform::fromTargetPoints (0, 0, resolvedPoints[0].x, resolvedPoints[0].y,
|
||||
w, 0, resolvedPoints[1].x, resolvedPoints[1].y,
|
||||
0, h, resolvedPoints[2].x, resolvedPoints[2].y);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void DrawableText::paint (Graphics& g)
|
||||
{
|
||||
transformContextToCorrectOrigin (g);
|
||||
|
||||
const float w = Line<float> (resolvedPoints[0], resolvedPoints[1]).getLength();
|
||||
const float h = Line<float> (resolvedPoints[0], resolvedPoints[2]).getLength();
|
||||
|
||||
g.addTransform (AffineTransform::fromTargetPoints (0, 0, resolvedPoints[0].x, resolvedPoints[0].y,
|
||||
w, 0, resolvedPoints[1].x, resolvedPoints[1].y,
|
||||
0, h, resolvedPoints[2].x, resolvedPoints[2].y));
|
||||
g.setFont (scaledFont);
|
||||
g.setColour (colour);
|
||||
|
||||
GlyphArrangement ga;
|
||||
const AffineTransform transform (getArrangementAndTransform (ga));
|
||||
ga.draw (g, transform);
|
||||
g.drawFittedText (text, Rectangle<int> (w, h), justification, 0x100000);
|
||||
}
|
||||
|
||||
Rectangle<float> DrawableText::getDrawableBounds() const
|
||||
|
|
|
|||
|
|
@ -149,7 +149,6 @@ private:
|
|||
bool registerCoordinates (RelativeCoordinatePositionerBase&);
|
||||
void recalculateCoordinates (Expression::Scope*);
|
||||
void refreshBounds();
|
||||
const AffineTransform getArrangementAndTransform (GlyphArrangement& glyphs) const;
|
||||
|
||||
DrawableText& operator= (const DrawableText&);
|
||||
JUCE_LEAK_DETECTOR (DrawableText)
|
||||
|
|
|
|||
|
|
@ -81,8 +81,7 @@ public:
|
|||
}
|
||||
|
||||
void draw (CodeEditorComponent& owner, Graphics& g, const Font& fontToUse,
|
||||
const float leftClip, const float rightClip,
|
||||
const float x, const int y, const int baselineOffset,
|
||||
const float rightClip, const float x, const int y,
|
||||
const int lineH, const float characterWidth,
|
||||
const Colour highlightColour) const
|
||||
{
|
||||
|
|
@ -93,9 +92,11 @@ public:
|
|||
roundToInt ((highlightColumnEnd - highlightColumnStart) * characterWidth), lineH);
|
||||
}
|
||||
|
||||
const float baselineY = (float) (y + baselineOffset);
|
||||
Colour lastColour (0x00000001);
|
||||
GlyphArrangement ga;
|
||||
|
||||
AttributedString as;
|
||||
as.setJustification (Justification::centredLeft);
|
||||
|
||||
int column = 0;
|
||||
|
||||
for (int i = 0; i < tokens.size(); ++i)
|
||||
|
|
@ -104,26 +105,12 @@ public:
|
|||
if (tokenX > rightClip)
|
||||
break;
|
||||
|
||||
SyntaxToken& token = tokens.getReference(i);
|
||||
|
||||
const Colour newColour (owner.getColourForTokenType (token.tokenType));
|
||||
if (lastColour != newColour)
|
||||
{
|
||||
ga.draw (g);
|
||||
ga.clear();
|
||||
|
||||
lastColour = newColour;
|
||||
g.setColour (newColour);
|
||||
}
|
||||
|
||||
const SyntaxToken& token = tokens.getReference(i);
|
||||
as.append (token.text, fontToUse, owner.getColourForTokenType (token.tokenType));
|
||||
column += token.length;
|
||||
|
||||
if (x + column * characterWidth >= leftClip)
|
||||
ga.addCurtailedLineOfText (fontToUse, token.text, tokenX, baselineY,
|
||||
(rightClip - tokenX) + characterWidth, false);
|
||||
}
|
||||
|
||||
ga.draw (g);
|
||||
as.draw (g, Rectangle<int> (x, y, 10000, lineH).toFloat());
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
@ -484,20 +471,18 @@ void CodeEditorComponent::paint (Graphics& g)
|
|||
g.reduceClipRegion (gutterSize, 0, verticalScrollBar.getX() - gutterSize, horizontalScrollBar.getY());
|
||||
|
||||
g.setFont (font);
|
||||
const int baselineOffset = (int) font.getAscent();
|
||||
const Colour highlightColour (findColour (CodeEditorComponent::highlightColourId));
|
||||
|
||||
const Rectangle<int> clip (g.getClipBounds());
|
||||
const int firstLineToDraw = jmax (0, clip.getY() / lineHeight);
|
||||
const int lastLineToDraw = jmin (lines.size(), clip.getBottom() / lineHeight + 1);
|
||||
const float x = (float) (gutterSize - xOffset * charWidth);
|
||||
const float leftClip = (float) clip.getX();
|
||||
const float rightClip = (float) clip.getRight();
|
||||
|
||||
for (int i = firstLineToDraw; i < lastLineToDraw; ++i)
|
||||
lines.getUnchecked(i)->draw (*this, g, font, leftClip, rightClip,
|
||||
x, lineHeight * i, baselineOffset,
|
||||
lineHeight, charWidth, highlightColour);
|
||||
lines.getUnchecked(i)->draw (*this, g, font, rightClip,
|
||||
x, lineHeight * i, lineHeight,
|
||||
charWidth, highlightColour);
|
||||
}
|
||||
|
||||
void CodeEditorComponent::setScrollbarThickness (const int thickness)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue