mirror of https://github.com/JakubMelka/PDF4QT.git
Performance optimalization of patch meshes
This commit is contained in:
parent
e9bff58c06
commit
67872a532f
|
@ -22,7 +22,7 @@
|
|||
namespace pdf
|
||||
{
|
||||
|
||||
static constexpr const std::array<std::pair<QChar, const char*>, 4281> glyphNameToUnicode = {
|
||||
static constexpr const std::array glyphNameToUnicode = {
|
||||
std::pair<QChar, const char*>{ QChar(0x0041), "A" }, // Character 'A' Letter, Uppercase
|
||||
std::pair<QChar, const char*>{ QChar(0x00C6), "AE" }, // Character 'Æ' Letter, Uppercase
|
||||
std::pair<QChar, const char*>{ QChar(0x01FC), "AEacute" }, // Character 'Ǽ' Letter, Uppercase
|
||||
|
@ -1831,6 +1831,10 @@ static constexpr const std::array<std::pair<QChar, const char*>, 4281> glyphName
|
|||
std::pair<QChar, const char*>{ QChar(0x01B9), "ezhreversed" }, // Character 'ƹ' Letter, Lowercase
|
||||
std::pair<QChar, const char*>{ QChar(0x01BA), "ezhtail" }, // Character 'ƺ' Letter, Lowercase
|
||||
std::pair<QChar, const char*>{ QChar(0x0066), "f" }, // Character 'f' Letter, Lowercase
|
||||
std::pair<QChar, const char*>{ QChar(0xFB00), "f_f" }, // Character 'ff' Letter, Lowercase // NOT LISTED IN UNICODE CHARACTER LIST
|
||||
std::pair<QChar, const char*>{ QChar(0xFB03), "f_f_i" }, // Character 'ffi' Letter, Lowercase // NOT LISTED IN UNICODE CHARACTER LIST
|
||||
std::pair<QChar, const char*>{ QChar(0xFB04), "f_f_l" }, // Character 'ffl' Letter, Lowercase // NOT LISTED IN UNICODE CHARACTER LIST
|
||||
std::pair<QChar, const char*>{ QChar(0xFB01), "f_i" }, // Character 'fi' Letter, Lowercase // NOT LISTED IN UNICODE CHARACTER LIST
|
||||
std::pair<QChar, const char*>{ QChar(0x095E), "fadeva" }, // Character 'फ़' Letter
|
||||
std::pair<QChar, const char*>{ QChar(0x0A5E), "fagurmukhi" }, // Character 'ਫ਼' Letter
|
||||
std::pair<QChar, const char*>{ QChar(0x2109), "fahrenheit" }, // Character '℉' Symbol
|
||||
|
|
|
@ -2604,6 +2604,13 @@ QPointF PDFTensorPatch::getValue(PDFReal u, PDFReal v, int derivativeOrderU, int
|
|||
|
||||
bool PDFTensorPatch::getUV(PDFReal& u, PDFReal& v, PDFReal x, PDFReal y, PDFReal epsilon, int maximalNumberOfSteps) const
|
||||
{
|
||||
// First we will text, if point (x, y) is in bounding rectangle of the patch.
|
||||
// If it isn't, then return false immediately, because point is not in tensor patch.
|
||||
if (!m_boundingBox.contains(x, y))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int i = 0;
|
||||
|
||||
// Jakub Melka: We are finding root of function F(u, v) defined as:
|
||||
|
@ -2816,6 +2823,27 @@ constexpr PDFReal PDFTensorPatch::B3(PDFReal t, int derivative)
|
|||
return std::numeric_limits<PDFReal>::signaling_NaN();
|
||||
}
|
||||
|
||||
void PDFTensorPatch::computeBoundingRectangle()
|
||||
{
|
||||
PDFReal xMin = std::numeric_limits<PDFReal>::infinity();
|
||||
PDFReal xMax = -xMin;
|
||||
PDFReal yMin = xMin;
|
||||
PDFReal yMax = xMax;
|
||||
|
||||
for (const auto& row : m_P)
|
||||
{
|
||||
for (const auto& point : row)
|
||||
{
|
||||
xMin = qMin(xMin, point.x());
|
||||
xMax = qMax(xMax, point.x());
|
||||
yMin = qMin(yMin, point.y());
|
||||
yMax = qMax(yMax, point.y());
|
||||
}
|
||||
}
|
||||
|
||||
m_boundingBox = QRectF(xMin, yMin, xMax - xMin, yMax - yMin);
|
||||
}
|
||||
|
||||
ShadingType PDFTensorProductPatchShading::getShadingType() const
|
||||
{
|
||||
return ShadingType::TensorProductPatchMesh;
|
||||
|
@ -3198,7 +3226,8 @@ void PDFTensorProductPatchShadingBase::fillMesh(PDFMesh& mesh,
|
|||
const PDFTensorPatch& patch,
|
||||
const PDFCMS* cms,
|
||||
RenderingIntent intent,
|
||||
PDFRenderErrorReporter* reporter) const
|
||||
PDFRenderErrorReporter* reporter,
|
||||
bool fastAlgorithm) const
|
||||
{
|
||||
// We implement algorithm similar to Ruppert's algorithm (see https://en.wikipedia.org/wiki/Ruppert%27s_algorithm), but
|
||||
// we do not need a mesh for FEM calculation, so we do not care about quality of the triangles (we can have triangles with
|
||||
|
@ -3216,24 +3245,31 @@ void PDFTensorProductPatchShadingBase::fillMesh(PDFMesh& mesh,
|
|||
|
||||
std::atomic<PDFReal> maximalCurvature(0.0);
|
||||
|
||||
Q_ASSERT(settings.patchTestPoints > 2);
|
||||
const PDFReal testPointScale = 1.0 / (settings.patchTestPoints - 1.0);
|
||||
PDFIntegerRange<PDFInteger> range(0, settings.patchTestPoints * settings.patchTestPoints);
|
||||
auto updateCurvature = [&](PDFInteger i)
|
||||
if (!fastAlgorithm)
|
||||
{
|
||||
PDFInteger row = i / settings.patchTestPoints;
|
||||
PDFInteger column = i % settings.patchTestPoints;
|
||||
Q_ASSERT(settings.patchTestPoints > 2);
|
||||
const PDFReal testPointScale = 1.0 / (settings.patchTestPoints - 1.0);
|
||||
PDFIntegerRange<PDFInteger> range(0, settings.patchTestPoints * settings.patchTestPoints);
|
||||
auto updateCurvature = [&](PDFInteger i)
|
||||
{
|
||||
PDFInteger row = i / settings.patchTestPoints;
|
||||
PDFInteger column = i % settings.patchTestPoints;
|
||||
|
||||
const PDFReal u = column * testPointScale;
|
||||
const PDFReal v = row * testPointScale;
|
||||
const PDFReal u = column * testPointScale;
|
||||
const PDFReal v = row * testPointScale;
|
||||
|
||||
const PDFReal curvature = patch.getCurvature_u(u, v) + patch.getCurvature_v(u, v);
|
||||
const PDFReal curvature = patch.getCurvature_u(u, v) + patch.getCurvature_v(u, v);
|
||||
|
||||
// Atomically update the maximum curvature
|
||||
PDFReal previousCurvature = maximalCurvature;
|
||||
while (previousCurvature < curvature && !maximalCurvature.compare_exchange_weak(previousCurvature, curvature)) { }
|
||||
};
|
||||
PDFExecutionPolicy::execute(PDFExecutionPolicy::Scope::Content, range.begin(), range.end(), updateCurvature);
|
||||
// Atomically update the maximum curvature
|
||||
PDFReal previousCurvature = maximalCurvature;
|
||||
while (previousCurvature < curvature && !maximalCurvature.compare_exchange_weak(previousCurvature, curvature)) { }
|
||||
};
|
||||
std::for_each(range.begin(), range.end(), updateCurvature);
|
||||
}
|
||||
else
|
||||
{
|
||||
maximalCurvature = std::numeric_limits<PDFReal>::infinity();
|
||||
}
|
||||
|
||||
auto getColorForUV = [&](PDFReal u, PDFReal v)
|
||||
{
|
||||
|
@ -3382,9 +3418,10 @@ void PDFTensorProductPatchShadingBase::fillMesh(PDFMesh& mesh,
|
|||
RenderingIntent intent,
|
||||
PDFRenderErrorReporter* reporter) const
|
||||
{
|
||||
const bool fastAlgorithm = patches.size() > 16;
|
||||
for (const auto& patch : patches)
|
||||
{
|
||||
fillMesh(mesh, settings, patch, cms, intent, reporter);
|
||||
fillMesh(mesh, settings, patch, cms, intent, reporter, fastAlgorithm);
|
||||
}
|
||||
|
||||
// Create bounding path
|
||||
|
|
|
@ -546,7 +546,7 @@ public:
|
|||
using PointMatrix = std::array<std::array<QPointF, 4>, 4>;
|
||||
using Colors = std::array<PDFColor, 4>;
|
||||
|
||||
explicit inline PDFTensorPatch(PointMatrix P, Colors colors) : m_P(P), m_colors(colors) { }
|
||||
explicit inline PDFTensorPatch(PointMatrix P, Colors colors) : m_P(P), m_colors(colors) { computeBoundingRectangle(); }
|
||||
|
||||
/// Calculates value at point in the patch.
|
||||
/// \param u Horizontal coordinate of the patch, must be in range [0, 1]
|
||||
|
@ -654,8 +654,11 @@ private:
|
|||
static constexpr PDFReal pow2(PDFReal x) { return x * x; }
|
||||
static constexpr PDFReal pow3(PDFReal x) { return x * x * x; }
|
||||
|
||||
void computeBoundingRectangle();
|
||||
|
||||
PointMatrix m_P = { };
|
||||
Colors m_colors = { };
|
||||
QRectF m_boundingBox; ///< Bounding box of the tensor product patch
|
||||
};
|
||||
|
||||
using PDFTensorPatches = std::vector<PDFTensorPatch>;
|
||||
|
@ -671,7 +674,7 @@ public:
|
|||
protected:
|
||||
struct Triangle;
|
||||
|
||||
void fillMesh(PDFMesh& mesh, const PDFMeshQualitySettings& settings, const PDFTensorPatch& patch, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const;
|
||||
void fillMesh(PDFMesh& mesh, const PDFMeshQualitySettings& settings, const PDFTensorPatch& patch, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter, bool fastAlgorithm) const;
|
||||
void fillMesh(PDFMesh& mesh, const QMatrix& patternSpaceToDeviceSpaceMatrix, const PDFMeshQualitySettings& settings, const PDFTensorPatches& patches, const PDFCMS* cms, RenderingIntent intent, PDFRenderErrorReporter* reporter) const;
|
||||
static void addTriangle(std::vector<Triangle>& triangles, const PDFTensorPatch& patch, std::array<QPointF, 3> uvCoordinates);
|
||||
|
||||
|
|
|
@ -1117,7 +1117,6 @@ void PDFTransparencyRenderer::collapseSpotColorsToDeviceColors(PDFFloatBitmapWit
|
|||
{
|
||||
case PDFAbstractColorSpace::ColorSpace::Separation:
|
||||
{
|
||||
|
||||
PDFFloatBitmap spotColorBitmap = bitmap.extractSpotChannel(i);
|
||||
PDFFloatBitmap processColorBitmap(spotColorBitmap.getWidth(), spotColorBitmap.getHeight(), PDFPixelFormat::createFormat(pixelFormat.getProcessColorChannelCount(), 0, false, pixelFormat.hasProcessColorsSubtractive(), false));
|
||||
if (!PDFAbstractColorSpace::transform(spotColor->colorSpace.data(), bitmap.getColorSpace().data(), getCMS(), getGraphicState()->getRenderingIntent(), spotColorBitmap.getPixels(), processColorBitmap.getPixels(), this))
|
||||
|
|
Loading…
Reference in New Issue