Merge pull request #6 from syncfusion/development
Added support for converting HTML to SVG
This commit is contained in:
Коммит
eedfe330b7
|
@ -895,7 +895,9 @@ bool QSvgPaintEngine::end()
|
|||
void QSvgPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm,
|
||||
const QRectF &sr)
|
||||
{
|
||||
drawImage(r, pm.toImage(), sr);
|
||||
QRect sourceRect = sr.toRect();
|
||||
QPixmap pixmap = sourceRect != pm.rect() ? pm.copy(sourceRect) : pm;
|
||||
drawImage(r, pixmap.toImage(), sr);
|
||||
}
|
||||
|
||||
void QSvgPaintEngine::drawImage(const QRectF &r, const QImage &image,
|
||||
|
|
|
@ -159,19 +159,6 @@ float Font::getGlyphsAndAdvancesForSimpleText(const TextRun& run, int from, int
|
|||
return beforeWidth;
|
||||
}
|
||||
|
||||
void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
|
||||
{
|
||||
// This glyph buffer holds our glyphs+advances+font data for each glyph.
|
||||
GlyphBuffer glyphBuffer;
|
||||
|
||||
float startX = point.x() + getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer);
|
||||
|
||||
if (glyphBuffer.isEmpty())
|
||||
return;
|
||||
|
||||
FloatPoint startPoint(startX, point.y());
|
||||
drawGlyphBuffer(context, run, glyphBuffer, startPoint);
|
||||
}
|
||||
|
||||
void Font::drawEmphasisMarksForSimpleText(GraphicsContext* context, const TextRun& run, const AtomicString& mark, const FloatPoint& point, int from, int to) const
|
||||
{
|
||||
|
|
|
@ -41,7 +41,6 @@ struct ExpectedTextRunSize {
|
|||
RefPtr<TextRun::RenderingContext> renderingContext;
|
||||
};
|
||||
|
||||
COMPILE_ASSERT(sizeof(TextRun) == sizeof(ExpectedTextRunSize), TextRun_is_not_of_expected_size);
|
||||
|
||||
bool TextRun::s_allowsRoundingHacks = false;
|
||||
|
||||
|
|
|
@ -62,6 +62,7 @@ public:
|
|||
#if ENABLE(8BIT_TEXTRUN)
|
||||
TextRun(const LChar* c, unsigned len, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true, RoundingHacks roundingHacks = RunRounding | WordRounding)
|
||||
: m_charactersLength(len)
|
||||
, m_characters(c)
|
||||
, m_len(len)
|
||||
, m_xpos(xpos)
|
||||
#if ENABLE(SVG)
|
||||
|
@ -85,6 +86,7 @@ public:
|
|||
|
||||
TextRun(const UChar* c, unsigned len, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true, RoundingHacks roundingHacks = RunRounding | WordRounding)
|
||||
: m_charactersLength(len)
|
||||
, m_characters(c)
|
||||
, m_len(len)
|
||||
, m_xpos(xpos)
|
||||
#if ENABLE(SVG)
|
||||
|
@ -107,6 +109,7 @@ public:
|
|||
|
||||
TextRun(const String& s, float xpos = 0, float expansion = 0, ExpansionBehavior expansionBehavior = AllowTrailingExpansion | ForbidLeadingExpansion, TextDirection direction = LTR, bool directionalOverride = false, bool characterScanForCodePath = true, RoundingHacks roundingHacks = RunRounding | WordRounding)
|
||||
: m_charactersLength(s.length())
|
||||
, m_characters(s.characters())
|
||||
, m_len(s.length())
|
||||
, m_xpos(xpos)
|
||||
#if ENABLE(SVG)
|
||||
|
@ -155,6 +158,13 @@ public:
|
|||
return result;
|
||||
}
|
||||
|
||||
UChar operator[](int i) const { ASSERT(i >= 0 && i < m_len); return m_characters[i]; }
|
||||
const UChar* data(int i) const { ASSERT(i >= 0 && i < m_len); return &m_characters[i]; }
|
||||
|
||||
const UChar* characters() const { return m_characters; }
|
||||
|
||||
void setText(const UChar* c, int len) { m_characters = c; m_len = len; }
|
||||
|
||||
UChar operator[](unsigned i) const { ASSERT_WITH_SECURITY_IMPLICATION(i < m_len); return is8Bit() ? m_data.characters8[i] :m_data.characters16[i]; }
|
||||
const LChar* data8(unsigned i) const { ASSERT_WITH_SECURITY_IMPLICATION(i < m_len); ASSERT(is8Bit()); return &m_data.characters8[i]; }
|
||||
const UChar* data16(unsigned i) const { ASSERT_WITH_SECURITY_IMPLICATION(i < m_len); ASSERT(!is8Bit()); return &m_data.characters16[i]; }
|
||||
|
@ -227,7 +237,7 @@ public:
|
|||
|
||||
private:
|
||||
static bool s_allowsRoundingHacks;
|
||||
|
||||
const UChar* m_characters;
|
||||
union {
|
||||
const LChar* characters8;
|
||||
const UChar* characters16;
|
||||
|
|
|
@ -37,6 +37,8 @@
|
|||
#include "TextRun.h"
|
||||
|
||||
#include <QBrush>
|
||||
#include <QPaintDevice>
|
||||
#include <QPaintEngine>
|
||||
#include <QPainter>
|
||||
#include <QPainterPath>
|
||||
#include <QPen>
|
||||
|
@ -173,6 +175,96 @@ static void drawQtGlyphRun(GraphicsContext* context, const QGlyphRun& qtGlyphRun
|
|||
}
|
||||
}
|
||||
|
||||
static void drawTextCommon(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to, const QFont& font, bool isComplexText)
|
||||
{
|
||||
|
||||
if (to < 0)
|
||||
to = run.length();
|
||||
|
||||
QPainter *p = ctx->platformContext();
|
||||
|
||||
QPen textFillPen;
|
||||
if (ctx->textDrawingMode() & TextModeFill)
|
||||
textFillPen = fillPenForContext(ctx);
|
||||
|
||||
QPen textStrokePen;
|
||||
if (ctx->textDrawingMode() & TextModeStroke)
|
||||
textStrokePen = strokePenForContext(ctx);
|
||||
|
||||
String sanitized = Font::normalizeSpaces(run.characters(), run.length());
|
||||
QString string = fromRawDataWithoutRef(sanitized);
|
||||
QPointF pt(point.x(), point.y());
|
||||
|
||||
p->setFont(font);
|
||||
|
||||
int flags = run.rtl() ? Qt::TextForceRightToLeft : Qt::TextForceLeftToRight;
|
||||
if (!isComplexText && !(ctx->textDrawingMode() & TextModeStroke))
|
||||
flags |= Qt::TextBypassShaping;
|
||||
|
||||
if (from > 0 || to < run.length()) {
|
||||
if (isComplexText) {
|
||||
QTextLayout layout(string, font);
|
||||
QTextLine line = setupLayout(&layout, run,false);
|
||||
float x1 = line.cursorToX(from);
|
||||
float x2 = line.cursorToX(to);
|
||||
if (x2 < x1)
|
||||
qSwap(x1, x2);
|
||||
|
||||
QFontMetrics fm(font);
|
||||
int ascent = fm.ascent();
|
||||
QRectF boundingRect(point.x() + x1, point.y() - ascent, x2 - x1, fm.height());
|
||||
QRectF clip = boundingRect;
|
||||
|
||||
QPainterPath textStrokePath;
|
||||
if (ctx->textDrawingMode() & TextModeStroke)
|
||||
textStrokePath.addText(pt, font, string);
|
||||
|
||||
|
||||
if (ctx->hasShadow()) {
|
||||
const GraphicsContextState& state = ctx->state();
|
||||
if (ctx->mustUseShadowBlur()) {
|
||||
ShadowBlur shadow(state);
|
||||
GraphicsContext* shadowContext = shadow.beginShadowLayer(ctx, boundingRect);
|
||||
if (shadowContext) {
|
||||
QPainter* shadowPainter = shadowContext->platformContext();
|
||||
shadowPainter->setPen(state.shadowColor);
|
||||
if (shadowContext->textDrawingMode() & TextModeFill)
|
||||
shadowPainter->drawText(pt, string, flags, run.expansion());
|
||||
else if (shadowContext->textDrawingMode() & TextModeStroke)
|
||||
shadowPainter->strokePath(textStrokePath, shadowPainter->pen());
|
||||
shadow.endShadowLayer(ctx);
|
||||
}
|
||||
}
|
||||
else {
|
||||
QPen previousPen = p->pen();
|
||||
p->setPen(state.shadowColor);
|
||||
const QPointF shadowOffset(state.shadowOffset.width(), state.shadowOffset.height());
|
||||
p->translate(shadowOffset);
|
||||
if (ctx->textDrawingMode() & TextModeFill)
|
||||
p->drawText(pt, string, flags, run.expansion());
|
||||
else if (ctx->textDrawingMode() & TextModeStroke)
|
||||
p->strokePath(textStrokePath, p->pen());
|
||||
p->translate(-shadowOffset);
|
||||
p->setPen(previousPen);
|
||||
}
|
||||
}
|
||||
p->setPen(textFillPen);
|
||||
line.draw(p, pt);
|
||||
p->restore();
|
||||
return;
|
||||
}
|
||||
int skipWidth = QFontMetrics(font).width(string, from, Qt::TextBypassShaping);
|
||||
pt.setX(pt.x() + skipWidth);
|
||||
string = fromRawDataWithoutRef(sanitized, from, to - from);
|
||||
}
|
||||
if (ctx->textDrawingMode() & TextModeFill) {
|
||||
QPen previousPen = p->pen();
|
||||
p->setPen(textFillPen);
|
||||
p->drawText(pt, string, flags, run.expansion());
|
||||
p->setPen(previousPen);
|
||||
}
|
||||
}
|
||||
|
||||
class TextLayout {
|
||||
public:
|
||||
static bool isNeeded(RenderText* text, const Font& font)
|
||||
|
@ -234,20 +326,7 @@ float Font::width(TextLayout& layout, unsigned from, unsigned len, HashSet<const
|
|||
return layout.width(from, len, fallbackFonts);
|
||||
}
|
||||
|
||||
void Font::drawComplexText(GraphicsContext* ctx, const TextRun& run, const FloatPoint& point, int from, int to) const
|
||||
{
|
||||
String sanitized = Font::normalizeSpaces(run.characters16(), run.length());
|
||||
const QString string = fromRawDataWithoutRef(sanitized);
|
||||
QTextLayout layout(string);
|
||||
layout.setRawFont(rawFont());
|
||||
initFormatForTextLayout(&layout, run);
|
||||
QTextLine line = setupLayout(&layout, run, true);
|
||||
const QPointF adjustedPoint(point.x(), point.y() - line.ascent());
|
||||
|
||||
QList<QGlyphRun> runs = line.glyphRuns(from, to - from);
|
||||
Q_FOREACH(QGlyphRun glyphRun, runs)
|
||||
drawQtGlyphRun(ctx, glyphRun, adjustedPoint, line.ascent());
|
||||
}
|
||||
|
||||
float Font::floatWidthForComplexText(const TextRun& run, HashSet<const SimpleFontData*>*, GlyphOverflow*) const
|
||||
{
|
||||
|
@ -379,6 +458,53 @@ void Font::drawGlyphs(GraphicsContext* context, const SimpleFontData* fontData,
|
|||
}
|
||||
|
||||
|
||||
void Font::drawSimpleText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
|
||||
{
|
||||
// This glyph buffer holds our glyphs+advances+font data for each glyph.
|
||||
QPainter* painter = context->platformContext();
|
||||
|
||||
if (painter->paintEngine()->type() == QPaintEngine::SVG)
|
||||
{
|
||||
drawTextCommon(context, run, point, from, to, syntheticFont(),/*font(), /* isComplexText = */false);
|
||||
}
|
||||
else
|
||||
{
|
||||
GlyphBuffer glyphBuffer;
|
||||
|
||||
float startX = point.x() + getGlyphsAndAdvancesForSimpleText(run, from, to, glyphBuffer);
|
||||
|
||||
if (glyphBuffer.isEmpty())
|
||||
return;
|
||||
|
||||
FloatPoint startPoint(startX, point.y());
|
||||
drawGlyphBuffer(context, run, glyphBuffer, startPoint);
|
||||
}
|
||||
|
||||
}
|
||||
void Font::drawComplexText(GraphicsContext* context, const TextRun& run, const FloatPoint& point, int from, int to) const
|
||||
{
|
||||
QPainter* painter = context->platformContext();
|
||||
if (painter->paintEngine()->type() == QPaintEngine::SVG)
|
||||
{
|
||||
drawTextCommon(context, run, point, from, to, syntheticFont(),/*font(), /* isComplexText = */true);
|
||||
}
|
||||
else
|
||||
{
|
||||
String sanitized = Font::normalizeSpaces(run.characters16(), run.length());
|
||||
const QString string = fromRawDataWithoutRef(sanitized);
|
||||
QTextLayout layout(string);
|
||||
layout.setRawFont(rawFont());
|
||||
initFormatForTextLayout(&layout, run);
|
||||
QTextLine line = setupLayout(&layout, run, true);
|
||||
const QPointF adjustedPoint(point.x(), point.y() - line.ascent());
|
||||
|
||||
QList<QGlyphRun> runs = line.glyphRuns(from, to - from);
|
||||
Q_FOREACH(QGlyphRun glyphRun, runs)
|
||||
drawQtGlyphRun(context, glyphRun, adjustedPoint, line.ascent());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Font::canExpandAroundIdeographsInComplexText()
|
||||
{
|
||||
return false;
|
||||
|
@ -399,7 +525,6 @@ QFont Font::syntheticFont() const
|
|||
return f;
|
||||
}
|
||||
|
||||
|
||||
QRawFont Font::rawFont() const
|
||||
{
|
||||
return primaryFont()->getQtRawFont();
|
||||
|
|
Загрузка…
Ссылка в новой задаче