void Builder::drawListItemBullet(Layout &l, float parentPosY) { Layout *parent = nullptr; if (_layoutStack.size() > 1) { parent = _layoutStack.at(_layoutStack.size() - 1); } const auto density = _media.density; auto origin = Vec2(roundf(l.position.x * density), roundf((parentPosY) * density)); FontStyle fStyle = l.node->getStyle().compileFontStyle(this); ParagraphStyle pStyle = l.node->getStyle().compileParagraphLayout(this); pStyle.textIndent.value = 0.0f; pStyle.textIndent.metric = style::Size::Metric::Px; auto baseFont = _fontSet->getLayout(fStyle)->getData(); Label label; Formatter reader(getFontSet(), &label._format, _media.density); reader.setOpticalAlignment(false); initFormatter(l, pStyle, parentPosY, reader, true); if (parent && parent->listItem != Layout::ListNone) { TextStyle textStyle = l.node->getStyle().compileTextLayout(this); WideString str = getListItemString(parent, l); reader.read(fStyle, textStyle, str, 0, 0); } reader.finalize(); float offset = fixLabelPagination(l, label); float finalHeight = reader.getHeight() / density + offset; float finalWidth = reader.getMaxLineX() / density; float x = 0, w = _media.surfaceSize.width; std::tie(x, w) = getFloatBounds(&l, origin.y / density, finalHeight); l.postObjects.emplace_back(Rect(x - l.position.x - finalWidth - pStyle.listOffset.computeValue(l.size.width, baseFont->metrics.height), origin.y / density - l.position.y, finalWidth, finalHeight), std::move(label)); }
ActualFont::Metrics VirtualFont::getMetrics(const string &lang) const { auto &fontSet = getFontSet(lang); if (fontSet.empty()) { return ActualFont::Metrics(); } else { return fontSet.front()->metrics * sizeRatio; } }
JNIEXPORT void JNICALL Java_gnu_java_awt_peer_gtk_FreetypeGlyphVector_getGlyphs (JNIEnv *env, jobject obj, jintArray codepoints, jintArray glyphs, jlongArray fonts) { PangoFcFont *default_font, *current_font; PangoFontset *pfs; jint *cpvals; jint length; int i; /* Set up default font and fontset */ default_font = getFont(env, obj); current_font = default_font; pfs = getFontSet(env, obj); /* Retrieve string information */ length = (*env)->GetArrayLength (env, codepoints); cpvals = (*env)->GetIntArrayElements (env, codepoints, NULL); jint *glyphArray = (*env)->GetIntArrayElements (env, glyphs, NULL); jlong *fontArray = (*env)->GetLongArrayElements (env, fonts, NULL); /* A design goal of Pango is to be threadsafe, but it's admitted that it is * not actually threadsafe at the moment. Using gdk locking here to be safe, * but I don't know if if actually helps at all... */ gdk_threads_enter(); for( i = 0; i < length; i++ ) { /* Ensure the current font has the requested character; if it doesn't, * try the default font before pulling a new font out of the fontset. * Once chosen, a font will be used until a character not in the font is * encountered. */ if (!pango_fc_font_has_char(current_font, cpvals[i])) { if (pango_fc_font_has_char(default_font, cpvals[i])) { current_font = default_font; g_object_ref(current_font); } else { current_font = (PangoFcFont*)pango_fontset_get_font(pfs, cpvals[i]); } } else { g_object_ref(current_font); } /* Get glyph, and store both glyph and pointer to font */ glyphArray[i] = (int)pango_fc_font_get_glyph(current_font, (gunichar)cpvals[i]); fontArray[i] = PTR_TO_JLONG(current_font); } gdk_threads_leave(); (*env)->ReleaseIntArrayElements (env, glyphs, glyphArray, 0); (*env)->ReleaseIntArrayElements (env, codepoints, cpvals, 0); (*env)->ReleaseLongArrayElements (env, fonts, fontArray, 0); }
const Font CtrlrFontManager::getFontFromString (const String &string) { //_DBG(string); if (!string.contains (";")) { //_DBG("\tno ; in string"); if (string == String::empty) { //_DBG("\tstring is empty, return default font"); return (Font (15.0f)); } return (Font::fromString(string)); } StringArray fontProps; fontProps.addTokens (string, ";", "\"\'"); Font font; if (fontProps[fontTypefaceName] != String::empty) { //_DBG("\tfont name not empty: "+fontProps[fontTypefaceName]); if (fontProps[fontSet] != String::empty && fontProps[fontSet].getIntValue() >= 0) { //_DBG("\tfont set is not empty and >= 0: "+_STR(fontProps[fontSet])); /* We need to fetch the typeface for the font from the correct font set */ Array<Font> &fontSetToUse = getFontSet((const FontSet)fontProps[fontSet].getIntValue()); for (int i=0; i<fontSetToUse.size(); i++) { if (fontSetToUse[i].getTypefaceName() == fontProps[fontTypefaceName]) { //_DBG("\tgot font from set, index: "+_STR(i)); font = fontSetToUse[i]; break; } } } else { /* The font set is not specified, fall back to JUCE to find the typeface name this will actualy be the OS set */ font.setTypefaceName (fontProps[fontTypefaceName]); } font.setHeight (fontProps[fontHeight].getFloatValue()); font.setBold (false); font.setUnderline (false); font.setItalic (false); if (fontProps[fontBold] != String::empty) font.setBold (fontProps[fontBold].getIntValue() ? true : false); if (fontProps[fontItalic] != String::empty) font.setItalic (fontProps[fontItalic].getIntValue() ? true : false); if (fontProps[fontUnderline] != String::empty) font.setUnderline (fontProps[fontUnderline].getIntValue() ? true : false); if (fontProps[fontKerning] != String::empty) font.setExtraKerningFactor (fontProps[fontKerning].getFloatValue()); if (fontProps[fontHorizontalScale] != String::empty) font.setHorizontalScale (fontProps[fontHorizontalScale].getFloatValue()); } return (font); }
LineLayout* VirtualFont::createLineLayout(const TextLine &line, boost::iterator_range<vector<TextRun>::const_iterator> range) { auto layout = new LineLayout(this, line.langHint, line.overallDirection); int averageCount = 0; map<hb_codepoint_t, Cluster> clusterMap; auto buffer = hb_buffer_create(); for (auto &run : range) { clusterMap.clear(); for (auto &font : getFontSet(run.language)) { if (font->reload()) { layout->maxHeight = std::max(layout->maxHeight, font->metrics.height); layout->maxAscent = std::max(layout->maxAscent, font->metrics.ascent); layout->maxDescent = std::max(layout->maxDescent, font->metrics.descent); layout->maxLineThickness = std::max(layout->maxLineThickness, font->metrics.lineThickness); layout->maxUnderlineOffset = std::max(layout->maxUnderlineOffset, font->metrics.underlineOffset); layout->averageStrikethroughOffset += font->metrics.strikethroughOffset; averageCount++; run.apply(line.text, buffer); hb_shape(font->hbFont, buffer, nullptr, 0); auto glyphCount = hb_buffer_get_length(buffer); auto glyphInfos = hb_buffer_get_glyph_infos(buffer, nullptr); auto glyphPositions = hb_buffer_get_glyph_positions(buffer, nullptr); bool hasMissingGlyphs = false; for (int i = 0; i < glyphCount; i++) { auto codepoint = glyphInfos[i].codepoint; auto cluster = glyphInfos[i].cluster; auto it = clusterMap.find(cluster); bool clusterFound = (it != clusterMap.end()); if (codepoint) { if (clusterFound && (it->second.font != font)) { continue; // CLUSTER FOUND, WITH ANOTHER FONT (E.G. SPACE) } else { auto offset = Vec2f(glyphPositions[i].x_offset, -glyphPositions[i].y_offset) * font->scale; float advance = glyphPositions[i].x_advance * font->scale.x; if (!properties.useMipmap) { offset.x = snap(offset.x); offset.y = snap(offset.y); advance = snap(advance); } if (clusterFound) { it->second.addShape(codepoint, offset, advance); } else { clusterMap.insert(make_pair(cluster, Cluster(font, run.tag, codepoint, offset, advance))); } } } else if (!clusterFound) { hasMissingGlyphs = true; } } if (!hasMissingGlyphs) { break; // NO NEED TO PROCEED TO THE NEXT FONT IN THE LIST } } } if (run.direction == HB_DIRECTION_RTL) { for (auto it = clusterMap.rbegin(); it != clusterMap.rend(); ++it) { layout->addCluster(it->second); } } else { for (auto it = clusterMap.begin(); it != clusterMap.end(); ++it) { layout->addCluster(it->second); } } } layout->averageStrikethroughOffset /= averageCount; hb_buffer_destroy(buffer); return layout; }
void init_nose(ModeInfo * mi) { Display *display = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); GC gc = MI_GC(mi); XGCValues gcv; nosestruct *np; if (noses == NULL) { if ((noses = (nosestruct *) calloc(MI_NUM_SCREENS(mi), sizeof (nosestruct))) == NULL) return; } np = &noses[MI_SCREEN(mi)]; np->width = MI_WIDTH(mi) + 2; np->height = MI_HEIGHT(mi) + 2; np->tinymode = (np->width + np->height < 4 * PIXMAP_SIZE); np->xs = PIXMAP_SIZE; np->ys = PIXMAP_SIZE; MI_CLEARWINDOW(mi); XSetForeground(display, gc, MI_WHITE_PIXEL(mi)); /* do not want any exposure events from XCopyPlane */ XSetGraphicsExposures(display, gc, False); if (mode_font == None) { #ifdef USE_MB mode_font = getFontSet(display); #else mode_font = getFont(display); #endif } if (np->noseGC[0] == None) if (!pickClothes(mi)) { free_nose(display, np); return; } np->words = getWords(MI_SCREEN(mi), MI_NUM_SCREENS(mi)); if (np->text_fg_gc == None && mode_font != None) { #ifndef USE_MB gcv.font = mode_font->fid; #endif gcv.graphics_exposures = False; gcv.foreground = MI_WHITE_PIXEL(mi); gcv.background = MI_BLACK_PIXEL(mi); if ((np->text_fg_gc = XCreateGC(display, window, #ifndef USE_MB GCFont | #endif GCForeground | GCBackground | GCGraphicsExposures, &gcv)) == None) { free_nose(display, np); return; } gcv.foreground = MI_BLACK_PIXEL(mi); gcv.background = MI_WHITE_PIXEL(mi); if ((np->text_bg_gc = XCreateGC(display, window, #ifndef USE_MB GCFont | #endif GCForeground | GCBackground | GCGraphicsExposures, &gcv)) == None) { free_nose(display, np); return; } } np->up = 1; if (np->tinymode) { int pos = NRAND(PIXMAPS); np->x = 0; np->y = 0; XCopyArea(display, np->position[pos], window, np->noseGC[pos], 0, 0, PIXMAP_SIZE, PIXMAP_SIZE, (np->width - PIXMAP_SIZE) / 2, (np->height - PIXMAP_SIZE) / 2); np->state = FREEZE; } else { np->x = np->width / 2; np->y = np->height / 2; np->state = MOVE; } XFlush(display); }
void init_image(ModeInfo * mi) { Display *display = MI_DISPLAY(mi); Window window = MI_WINDOW(mi); imagestruct *ip; int i; if (ims == NULL) { if ((ims = (imagestruct *) calloc(MI_NUM_SCREENS(mi), sizeof (imagestruct))) == NULL) return; } ip = &ims[MI_SCREEN(mi)]; if (message && *message) { XGCValues gcv; #ifdef USE_MB mode_font = getFontSet(display); ip->text_descent = 0; ip->text_ascent = getFontHeight(mode_font); #else mode_font = getFont(display); ip->text_descent = mode_font->descent; ip->text_ascent = mode_font->ascent; #endif if (mode_font == None) { return; } initStrings(mi); ip->black = MI_BLACK_PIXEL(mi); free_image(display, ip); ip->pixh = (ip->lines + DELTA) * ip->text_height; if ((ip->pixmap = XCreatePixmap(display, window, ip->pixw, ip->pixh, 1)) == None) { free_image(display, ip); ip->pixw = 0; ip->pixh = 0; return; } #ifndef USE_MB gcv.font = mode_font->fid; #endif gcv.background = 0; gcv.foreground = 1; gcv.graphics_exposures = False; if ((ip->fgGC = XCreateGC(display, ip->pixmap, GCForeground | GCBackground | GCGraphicsExposures #ifndef USE_MB | GCFont #endif , &gcv)) == None) { free_image(display, ip); ip->pixw = 0; ip->pixh = 0; return; } gcv.foreground = 0; if ((ip->bgGC = XCreateGC(display, ip->pixmap, GCForeground | GCBackground | GCGraphicsExposures #ifndef USE_MB | GCFont #endif , &gcv)) == None) { free_image(display, ip); ip->pixw = 0; ip->pixh = 0; return; } XFillRectangle(display, ip->pixmap, ip->bgGC, 0, 0, ip->pixw, ip->pixh); XSetForeground(display, MI_GC(mi), MI_WHITE_PIXEL(mi)); for (i = 0; i < ip->lines; i++) { DrawString(display, ip->pixmap, ip->fgGC, ip->textStart[i], ip->text_ascent + i * ip->text_height, ip->strnew[i], strlen(ip->strnew[i])); } /* don't want any exposure events from XCopyPlane */ XSetGraphicsExposures(display, MI_GC(mi), False); } else if (!initLogo(mi)) return; ip->width = MI_WIDTH(mi); ip->height = MI_HEIGHT(mi); if (ip->width > ip->pixw) ip->ncols = ip->width / ip->pixw; else ip->ncols = 1; if (ip->height > ip->pixh) ip->nrows = ip->height / ip->pixh; else ip->nrows = 1; ip->border.x = ip->width - ip->ncols * ip->pixw; ip->border.y = ip->height - ip->nrows * ip->pixh; ip->iconcount = MI_COUNT(mi); if (ip->iconcount < -MINICONS) ip->iconcount = NRAND(-ip->iconcount - MINICONS + 1) + MINICONS; else if (ip->iconcount < MINICONS) ip->iconcount = MINICONS; if (ip->iconcount > ip->ncols * ip->nrows) ip->iconcount = ip->ncols * ip->nrows; if (ip->icons != NULL) free(ip->icons); if ((ip->icons = (imagetype *) malloc(ip->iconcount * sizeof (imagetype))) == NULL) { free_image(display, ip); return; } for (i = 0; i < ip->iconcount; i++) ip->icons[i].x = -1; if (!(message && *message)) { MI_CLEARWINDOWCOLORMAP(mi, ip->bgGC, ip->black); } draw_image(mi); }