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);
}
Exemple #4
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;
        }
Exemple #6
0
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);
}
Exemple #7
0
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);
}