📄 qpaintengine_raster.cpp
字号:
++x; continue; } if (current == NSPANS) { d->penData.blend(current, spans, &d->penData); current = 0; } spans[current].x = x + rx; spans[current].y = y + ry; spans[current].coverage = 255; int len = 1; ++x; // extend span until we find a different one. while (x < w && monoVal(scanline, x)) { ++x; ++len; } spans[current].len = len; ++current; } scanline += bpl; } } else { for (int y=y0; y < h; ++y) { for (int x = x0; x < w; ) { // Skip those with 0 coverage if (scanline[x] == 0) { ++x; continue; } if (current == NSPANS) { d->penData.blend(current, spans, &d->penData); current = 0; } int coverage = scanline[x]; spans[current].x = x + rx; spans[current].y = y + ry; spans[current].coverage = coverage; int len = 1; ++x; // extend span until we find a different one. while (x < w && scanline[x] == coverage) { ++x; ++len; } spans[current].len = len; ++current; } scanline += bpl; } }// qDebug() << "alphaPenBlt: num spans=" << current// << "span:" << spans->x << spans->y << spans->len << spans->coverage; // Call span func for current set of spans. if (current != 0) d->penData.blend(current, spans, &d->penData);}/* Fills a rect with the current pen */void QRasterPaintEngine::qwsFillRect(int x, int y, int w, int h){ Q_D(QRasterPaintEngine); int x1 = qMax(x,0); int x2 = qMin(x+w, d->rasterBuffer->width()); int y1 = qMax(y, 0); int y2 = qMin(y+h, d->rasterBuffer->height());; int len = x2 - x1; if (d->penData.blend && len > 0) { QT_FT_Span span; span.x = x1; span.len = x2 - x1; span.y = y; span.coverage = 255; // draw the fill for (int y=y1; y<y2; ++y) { d->penData.blend(1, &span, &d->penData); } }}#endif#ifdef Q_WS_X11void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem){ QPaintEngine::drawTextItem(p, textItem); // #####}#else#if defined(Q_WS_WIN)bool QRasterPaintEngine::drawTextInFontBuffer(const QRect &devRect, int xmin, int ymin, int xmax, int ymax, const QTextItem &textItem, bool clearType, qreal leftBearingReserve){ Q_D(QRasterPaintEngine); const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem); if (d->mono_surface) { // Some extra work to get proper rasterization of text on monochrome targets HBITMAP bitmap = CreateBitmap(devRect.width(), devRect.height(), 1, 1, 0); HDC hdc = CreateCompatibleDC(qt_win_display_dc()); HGDIOBJ null_bitmap = SelectObject(hdc, bitmap); SelectObject(hdc, GetStockObject(WHITE_BRUSH)); SelectObject(hdc, GetStockObject(NULL_PEN)); Rectangle(hdc, 0, 0, devRect.width() + 1, devRect.height() + 1); // Fill buffer with stuff SelectObject(hdc, GetStockObject(BLACK_BRUSH)); SelectObject(hdc, GetStockObject(BLACK_PEN)); SetTextColor(hdc, RGB(0,0,0)); qt_draw_text_item(QPoint(qRound(leftBearingReserve), ti.ascent.toInt()), ti, hdc); BitBlt(d->fontRasterBuffer->hdc(), 0, 0, devRect.width(), devRect.height(), hdc, 0, 0, SRCCOPY); SelectObject(hdc, null_bitmap); DeleteObject(bitmap); DeleteDC(hdc); return false; } else { // Let Windows handle the composition of background and foreground for cleartype text QRgb penColor = 0; if (clearType) { penColor = d->penData.solid.color; // Copy background from raster buffer for (int y=ymin; y<ymax; ++y) { QRgb *sourceScanline = (QRgb *) d->rasterBuffer->scanLine(y); QRgb *destScanline = (QRgb *) d->fontRasterBuffer->scanLine(y - devRect.y()); for (int x=xmin; x<xmax; ++x) { // If the background is transparent, set it to completely opaque so we will // recognize it after Windows screws up the alpha channel of font buffer. // Otherwise, just copy the contents. if (qAlpha(sourceScanline[x]) == 0x00) destScanline[x - devRect.x()] |= 0xff000000; else destScanline[x - devRect.x()] = sourceScanline[x]; } } } else { d->fontRasterBuffer->resetBuffer(255); } // Draw the text item if (d->clear_type_text) { COLORREF cf = RGB(qRed(penColor), qGreen(penColor), qBlue(penColor)); SelectObject(d->fontRasterBuffer->hdc(), CreateSolidBrush(cf)); SelectObject(d->fontRasterBuffer->hdc(), CreatePen(PS_SOLID, 1, cf)); SetTextColor(d->fontRasterBuffer->hdc(), cf); } qt_draw_text_item(QPoint(qRound(leftBearingReserve), ti.ascent.toInt()), ti, d->fontRasterBuffer->hdc()); if (d->clear_type_text) { DeleteObject(SelectObject(d->fontRasterBuffer->hdc(),GetStockObject(NULL_BRUSH))); DeleteObject(SelectObject(d->fontRasterBuffer->hdc(),GetStockObject(BLACK_PEN))); } // Clean up alpha channel if (clearType) { for (int y=ymin; y<ymax; ++y) { QRgb *scanline = (QRgb *) d->fontRasterBuffer->scanLine(y - devRect.y()); QRgb *rbScanline = (QRgb *) d->rasterBuffer->scanLine(y); for (int x=xmin; x<xmax; ++x) { // If alpha is 0, then Windows has drawn text on top of the pixel, so set // the pixel to opaque. Otherwise, Windows has not touched the pixel, so // we can set it to transparent so the background shines through instead. switch (qAlpha(scanline[x - devRect.x()])) { case 0x0: // Special case: If Windows has drawn on top of a transparent pixel, then // we bail out. This is an attempt at avoiding the problem where Windows // has no background to use for composition, but also minimizing the // number of cases hit by the fall back. // ### This is far from optimal. if (qAlpha(rbScanline[x]) == 0) { return drawTextInFontBuffer(devRect, xmin, ymin, xmax, ymax, textItem, false, leftBearingReserve); } scanline[x - devRect.x()] |= 0xff000000; break ; default: scanline[x - devRect.x()] = 0x0; break ; }; } } } } return clearType;}#endif // Q_WS_WINvoid QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem){ const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);#ifdef QT_DEBUG_DRAW printf(" - QRasterPaintEngine::drawTextItem(), (%.2f,%.2f), string=%s\n", p.x(), p.y(), QString::fromRawData(ti.chars, ti.num_chars).toLatin1().data());#endif Q_D(QRasterPaintEngine);#if defined(Q_WS_WIN) if (!d->penData.blend) return; if (d->txop >= QPainterPrivate::TxScale) { QPaintEngine::drawTextItem(p, textItem); return; } // Only support cleartype for solid pens, 32 bit target buffers and when the pen color is // opaque bool clearType = d->clear_type_text && d->penData.type == QSpanData::Solid && d->deviceDepth == 32 && qAlpha(d->penData.solid.color) == 255; QFixed x_buffering = ti.ascent; // Hack to reserve some space on the left side of the string in case // the character has a large negative bearing (e.g. it should be drawn on top // of the previous character) qreal leftBearingReserve = ti.fontEngine->maxCharWidth(); QRectF logRect(p.x() - leftBearingReserve, p.y() - ti.ascent.toReal(), (ti.width + x_buffering).toReal() + leftBearingReserve, (ti.ascent + ti.descent + 1).toReal()); QRect devRect = d->matrix.mapRect(logRect).toRect(); if(devRect.width() == 0 || devRect.height() == 0) return; d->fontRasterBuffer->prepare(devRect.width(), devRect.height()); // Boundaries int ymax = qMin(devRect.y() + devRect.height(), d->rasterBuffer->height()); int ymin = qMax(devRect.y(), 0); int xmax = qMin(devRect.x() + devRect.width(), d->rasterBuffer->width()); int xmin = qMax(devRect.x(), 0); QClipData *clip = d->rasterBuffer->clipEnabled ? d->rasterBuffer->clip : 0; if (clip) { xmin = qMax(xmin, clip->xmin); xmax = qMin(xmax, clip->xmax); ymin = qMax(ymin, clip->ymin); ymax = qMin(ymax, clip->ymax); } if (xmax - xmin <= 0 || ymax - ymin <= 0) return; // Fill the font raster buffer with text clearType = drawTextInFontBuffer(devRect, xmin, ymin, xmax, ymax, textItem, clearType, leftBearingReserve); const int NSPANS = 256; QSpan spans[NSPANS]; int current = 0; if (d->mono_surface) { for (int y=ymin; y<ymax; ++y) { QRgb *scanline = (QRgb *) d->fontRasterBuffer->scanLine(y - devRect.y()) - devRect.x(); // Generate spans for this y coord for (int x = xmin; x<xmax; ) { // Skip those with 0 coverage (black on white so inverted) while (x < xmax && qBlue(scanline[x]) > 0x80) ++x; if (x >= xmax) break; QT_FT_Span span = { x, 0, y, 255 }; // extend span until we find a different one. while (x < xmax && qBlue(scanline[x]) < 0x80) ++x; span.len = x - span.x; if (current == NSPANS) { d->penData.blend(current, spans, &d->penData); current = 0; } spans[current++] = span; } } } else if (clearType) { QSpanData data; data.init(d->rasterBuffer); data.type = QSpanData::Texture; data.texture.type = TextureData::Plain; data.texture.imageData = d->fontRasterBuffer->buffer(); data.texture.width = d->fontRasterBuffer->bytesPerLine() / 4; data.texture.height = d->fontRasterBuffer->height(); data.texture.bytesPerLine = d->fontRasterBuffer->bytesPerLine(); data.texture.hasAlpha = true; data.bilinear = false; data.texture.format = QImage::Format_ARGB32_Premultiplied; data.texture.colorTable = 0; data.dx = -devRect.x(); data.dy = -devRect.y(); data.adjustSpanMethods(); fillRect(QRect(xmin, ymin, xmax - xmin, ymax - ymin), &data); } else if (d->clear_type_text) { for (int y=ymin; y<ymax; ++y) { QRgb *scanline = (QRgb *) d->fontRasterBuffer->scanLine(y - devRect.y()) - devRect.x(); // Generate spans for this y coord for (int x = xmin; x<xmax; ) { // Skip those with 0 coverage (black on white so inverted) while (x < xmax && qGray(scanline[x]) == 255) ++x; if (x >= xmax) break; int prev = qGray(scanline[x]); QT_FT_Span span = { x, 0, y, 255 - prev }; // extend span until we find a different one. while (x < xmax && qGray(scanline[x]) == prev) ++x; span.len = x - span.x; if (current == NSPANS) { d->penData.blend(current, spans, &d->penData); current = 0; } spans[current++] = span; } } } else { // For the noncleartype/grayscale text we can look at only one color component, // and save a bit of qGray effort... for (int y=ymin; y<ymax; ++y) { QRgb *scanline = (QRgb *) d->fontRasterBuffer->scanLine(y - devRect.y()) - devRect.x(); // Generate spans for this y coord for (int x = xmin; x<xmax; ) { // Skip those with 0 coverage (black on white so inverted) while (x < xmax && qBlue(scanline[x]) == 255) ++x; if (x >= xmax) break; int prev = qBlue(scanline[x]); QT_FT_Span span = { x, 0, y, 255 - prev }; // extend span until we find a different one. while (x < xmax && qBlue(scanline[x]) == prev) ++x; span.len = x - span.x; if (current == NSPANS) { d->penData.blend(current, spans, &d->penData); current = 0; } spans[current++] = span; } } } if (current != 0) d->penData.blend(current, spans, &d->penData); return;#elif defined Q_WS_QWS if (d->txop < QPainterPrivate::TxScale) {#ifndef QT_NO_FREETYPE if (!(ti.fontEngine->type() == QFontEngine::Freetype && static_cast<QFontEngineFT*>(ti.fontEngine)->drawAsOutline()))#endif { ti.fontEngine->draw(this, qRound(p.x()), qRound(p.y()), ti); return; } }#endif // Q_WS_WIN // Fallthrough for embedded and default for mac. bool aa = d->antialiased; d->antialiased = true; QPaintEngine::drawTextItem(p, ti); d->antialiased = aa; return;}#endifvoid Q
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -